W jaki sposób można utworzyć kontroler interfejsu Web API, który generuje i zwraca skompresowany plik ZIP przesyłany strumieniowo z kolekcji plików JPEG w pamięci (obiekty MemoryStream). Próbuję użyć biblioteki DotNetZip. Znalazłem ten przykład: http://www.4guysfromrolla.com/articles/092910-1.aspx#postadlink. Ale Response.OutputStream nie jest dostępny w Web API i dlatego technika ta nie działa. Dlatego próbowałem zapisać plik zip do nowego MemoryStream; ale rzucił. Wreszcie próbowałem używać PushStreamContent. Oto mój kod:Korzystając z interfejsu ASP.NET Web API, w jaki sposób kontroler może zwrócić kolekcję strumieniowych obrazów skompresowanych przy użyciu biblioteki DotNetZip?
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;
}
}
zipFile.Save (memStream) wyrzuca pustą referencję. Ale ani zipFile, ani memStream nie są puste i nie ma wewnętrznego wyjątku. Więc nie jestem pewien, co powoduje odwołanie zerowe. Mam bardzo małe doświadczenie z Web API, strumieniami pamięci i nigdy wcześniej nie korzystałem z DotNetZipLibrary. Jest to kontynuacja tego pytania: Want an efficient ASP.NET Web API controller that can reliably return 30 to 50 ~3MB JPEGs
Wszelkie pomysły? dzięki!
nie widzę niczego złego w kodzie WebAPI. Jednak użyłbym StreamContent zamiast ByteArrayContent. Rozumiem, że powiedziałeś, że uzyskałeś referencję zerową w pliku zipFile.Save, ale spróbowałbym usunąć use() wokół nowego pliku ZipFile(). –
Dzięki. Niestety usunięcie użycia nie pomogło. Nadal rzuca wyjątek NullReferenceException na zipFile.Save (...). Oto ślad: na Ionic.Zlib.ParallelDeflateOutputStream._Flush (Boolean lastInput) w Ionic.Zlib.ParallelDeflateOutputStream.Close() w Ionic.Zip.ZipEntry.FinishOutputStream (strumień s, CountingStream entryCounter szyfratora, potok, strumień sprężarki, CrcCalculatorStream wyjście) w Ionic.Zip.ZipEntry._WriteEntryData (Stream s) na Ionic.Zip.ZipEntry.Write (Stream s) na Ionic.Zip.ZipFile.Save() na Ionic.Zip.ZipFile.Save (Stream outputStream) – CalvinDale
Po wykonaniu bitmap.Save, co jest pozycja memoryStream? Może być konieczne ustawienie parametru memoryStream.Position = 0, ponieważ w przeciwnym razie można zapisać zero-bajtów w pliku zip. –