我正在使用 SharpZipLib 中的 ZipOutputStream ,我希望将其创建的压缩内容直接上传到我的MVC帖子操作中。我成功地将其发布,但是当我的MVC操作进入MVC操作时,我的action方法的参数为已发布的数据。
这是我用来测试它的测试代码:
public void UploadController_CanUploadTest()
{
string xml = "<test>xml test</test>"
string url = "http://localhost:49316/Api/DataUpload/Upload/";
WebClient client = new WebClient();
var cc= new CredentialCache();
cc.Add(new Uri(url),
"Basic",
new NetworkCredential("Testuser", "user"));
client.Credentials = cc;
string _UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
client.Headers.Add(HttpRequestHeader.UserAgent, _UserAgent);
client.Headers["Content-type"] = "application/x-www-form-urlencoded";
using (var stream = client.OpenWrite(url, "POST"))
{
Zipped zip = new Zipped(stream, Encoding.UTF8, false);
FileContent content = new FileContent("Upload", xml);
var uploads = new List<FileContent>();
uploads.Add(content);
zip.Compress(uploads);
stream.Flush();
stream.Close();
}
}
这是我的压缩类包装器:
public class Zipped : ICompression, IDisposable
{
private Stream _stream = null;
private bool _closeStreamOnDispose = true;
private Encoding _encoding;
public Zipped()
: this(new MemoryStream())
{
}
public Zipped(Stream stream)
: this(stream, Encoding.UTF8, true)
{
}
public Zipped(Stream stream, Encoding encoding)
: this(stream, encoding, true)
{
}
public Zipped(Stream stream, Encoding encoding, bool closeStreamOnDispose)
{
_stream = stream;
_closeStreamOnDispose = closeStreamOnDispose;
_encoding = encoding;
}
public Stream Compress(IList<FileContent> dataList)
{
ZipOutputStream outputStream = new ZipOutputStream(_stream);
outputStream.SetLevel(9);
foreach (var data in dataList)
{
ZipEntry entry = new ZipEntry(data.Name);
entry.CompressionMethod = CompressionMethod.Deflated;
outputStream.PutNextEntry(entry);
byte[] dataAsByteArray = _encoding.GetBytes(data.Content);
outputStream.Write(dataAsByteArray, 0, dataAsByteArray.Length);
outputStream.CloseEntry();
}
outputStream.IsStreamOwner = false;
outputStream.Flush();
outputStream.Close();
return _stream;
}
public List<FileContent> DeCompress()
{
ZipInputStream inputStream = new ZipInputStream(_stream);
ZipEntry entry = inputStream.GetNextEntry();
List<FileContent> dataList = new List<FileContent>();
while(entry != null)
{
string entryFileName = entry.Name;
byte[] buffer = new byte[4096]; // 4K is optimum
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
using (MemoryStream tempMemoryStream = new MemoryStream())
{
StreamUtils.Copy(inputStream, tempMemoryStream, buffer);
string copied = _encoding.GetString(tempMemoryStream.ToArray());
dataList.Add(new FileContent(entry.Name, copied));
}
entry = inputStream.GetNextEntry();
}
return dataList;
}
public void Dispose()
{
if(_closeStreamOnDispose)
_stream.Dispose();
}
这是我简单的MVC操作:
[HttpPost]
public ActionResult Upload(HttpPostedFileBase uploaded)
{
// uploaded is null at this point
}
答案 0 :(得分:1)
如果您想在控制器操作中使用HttpPostedFileBase
,则需要从客户端发送multipart/form-data
请求,而不是application/x-www-form-urlencoded
。
实际上,您将内容类型设置为application/x-www-form-urlencoded
,但您并不尊重这一点,因为您正在将原始字节直接写入无效的请求。嗯,实际上它并不尊重HTTP协议标准,但如果您从控制器读取原始请求流而不是使用HttpPostedFileBase
,它仍然可以工作。我不建议你走那条路。
因此,您发送的正确HTTP请求必须如下所示:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="uploaded"; filename="input.zip"
Content-Type: application/zip
... byte contents of the zip ...
--AaB03x--
必须选择边界,使其不会出现在文件内容的任何位置。
我在博客上写了一个关于如何upload multiple files的例子。