Cal*_*ale 14 .net c# dotnetzip asp.net-web-api
如何创建Web API控制器,生成并返回从内存中JPEG文件(MemoryStream对象)集合流式传输的压缩zip文件.我正在尝试使用DotNetZip库.我找到了这个例子:http://www.4guysfromrolla.com/articles/092910-1.aspx#postadlink.但是,Response.OutputStream在Web API中不可用,因此该技术不能正常工作.因此我尝试将zip文件保存到新的MemoryStream中; 但它扔了.最后,我尝试使用PushStreamContent.这是我的代码:
public HttpResponseMessage Get(string imageIDsList) {
var imageIDs = imageIDsList.Split(',').Select(_ => int.Parse(_));
var any = _dataContext.DeepZoomImages.Select(_ => _.ImageID).Where(_ => imageIDs.Contains(_)).Any();
if (!any) {
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
var dzImages = _dataContext.DeepZoomImages.Where(_ => imageIDs.Contains(_.ImageID));
using (var zipFile = new ZipFile()) {
foreach (var dzImage in dzImages) {
var bitmap = GetFullSizeBitmap(dzImage);
var memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Jpeg);
var fileName = string.Format("{0}.jpg", dzImage.ImageName);
zipFile.AddEntry(fileName, memoryStream);
}
var response = new HttpResponseMessage(HttpStatusCode.OK);
var memStream = new MemoryStream();
zipFile.Save(memStream); //Null Reference Exception
response.Content = new ByteArrayContent(memStream.ToArray());
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = string.Format("{0}_images.zip", dzImages.Count()) };
return response;
}
}
Run Code Online (Sandbox Code Playgroud)
zipFile.Save(memStream)抛出空引用.但是zipFile和memStream都不为null,并且没有内部异常.所以我不确定是什么导致了null引用.我对Web API,内存流的经验很少,而且之前我从未使用过DotNetZipLibrary.这是对这个问题的跟进:想要一个高效的ASP.NET Web API控制器,它可以可靠地返回30到50~3MB的JPEG
有任何想法吗?谢谢!
Fel*_*ala 16
更通用的方法可以这样工作:
using Ionic.Zip; // from NUGET-Package "DotNetZip"
public HttpResponseMessage Zipped()
{
using (var zipFile = new ZipFile())
{
// add all files you need from disk, database or memory
// zipFile.AddEntry(...);
return ZipContentResult(zipFile);
}
}
protected HttpResponseMessage ZipContentResult(ZipFile zipFile)
{
// inspired from http://stackoverflow.com/a/16171977/92756
var pushStreamContent = new PushStreamContent((stream, content, context) =>
{
zipFile.Save(stream);
stream.Close(); // After save we close the stream to signal that we are done writing.
}, "application/zip");
return new HttpResponseMessage(HttpStatusCode.OK) {Content = pushStreamContent};
}
Run Code Online (Sandbox Code Playgroud)
该ZipContentResult
方法也可以存在于基类中,并可以在任何api控制器中的任何其他操作中使用.
该PushStreamContent类可以在这种情况下使用,以消除对MemoryStream的需要,至少在整个压缩文件.它可以像这样实现:
public HttpResponseMessage Get(string imageIDsList)
{
var imageIDs = imageIDsList.Split(',').Select(_ => int.Parse(_));
var any = _dataContext.DeepZoomImages.Select(_ => _.ImageID).Where(_ => imageIDs.Contains(_)).Any();
if (!any)
{
throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.NotFound));
}
var dzImages = _dataContext.DeepZoomImages.Where(_ => imageIDs.Contains(_.ImageID));
var streamContent = new PushStreamContent((outputStream, httpContext, transportContent) =>
{
try
{
using (var zipFile = new ZipFile())
{
foreach (var dzImage in dzImages)
{
var bitmap = GetFullSizeBitmap(dzImage);
var memoryStream = new MemoryStream();
bitmap.Save(memoryStream, ImageFormat.Jpeg);
memoryStream.Position = 0;
var fileName = string.Format("{0}.jpg", dzImage.ImageName);
zipFile.AddEntry(fileName, memoryStream);
}
zipFile.Save(outputStream); //Null Reference Exception
}
}
finally
{
outputStream.Close();
}
});
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/zip");
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = string.Format("{0}_images.zip", dzImages.Count()),
};
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = streamContent
};
return response;
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,使用ZipOutputStream类动态创建zip而不是使用ZipFile 可以更加动态地创建它.在这种情况下,不需要每个位图的MemoryStream.
归档时间: |
|
查看次数: |
14178 次 |
最近记录: |