Ton*_*_89 4 .net c# memorystream asp.net-web-api2
所以我正在尝试创建一个 zip 存档并从我的 web api 返回它。从 angular 2 站点调用控制器。当前 zip 文件已创建,但当我打开它时,我收到一条无效消息。最初我在 using 语句中有流,但必须更改它,因为它们在请求完成之前被处理。
我需要的是创建 zip 文件,将 csv 文件添加到其内容中。然后返回zip文件。但是 zip 文件总是无效的。我已经阅读了需要处理 zip 存档才能写入其内容的内容,但是我不确定实现此目的的最佳方法是什么。感谢您的任何指导。
public async Task<IHttpActionResult> ExportReport(int id, ReportModel report)
{
try
{
var result = await ReportGenerationService.ExportReportForId(id, report.Page, report.PageSize, report.SortField, report.SortDir, report.SearchTerm, report.StartDate, report.EndDate, report.UserId, report.TeamId, report.SelectedDateItem);
if (result != null)
{
var compressedFileStream = new MemoryStream();
var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false);
var zipEntry = zipArchive.CreateEntry("textExport.csv");
var origionalFileSteam = new MemoryStream(result.ExportToBytes());
var zipEntryStream = zipEntry.Open();
origionalFileSteam.CopyTo(zipEntryStream);
var response = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StreamContent(compressedFileStream)};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Export.zip"
};
var t = compressedFileStream.CanRead;
return ResponseMessage(response);
}
return NotFound();
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
响应 using 语句:
有一次,我将所有内容都包含在 using 语句中,但响应会失败,因为流已经被处理。你可以在下面看到这一点。
public async Task<IHttpActionResult> ExportReport(int id, ReportModel report)
{
try
{
var result = await ReportGenerationService.ExportReportForId(id, report.Page, report.PageSize, report.SortField, report.SortDir, report.SearchTerm, report.StartDate, report.EndDate, report.UserId, report.TeamId, report.SelectedDateItem);
if (result != null)
{
var compressedFileStream = new MemoryStream();
var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false);
//Create a zip entry for each attachment
var zipEntry = zipArchive.CreateEntry("textExport.csv");
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(result.ExportToBytes()))
using (var zipEntryStream = zipEntry.Open()) {
//Copy the attachment stream to the zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
compressedFileStream.Position = 0;
var response = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StreamContent(compressedFileStream)};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Export.zip"
};
return ResponseMessage(response);
}
return NotFound();
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
处理 zip 存档时正在处理内存流。
您应该处理存档以强制其将其内容写入其底层内存流,但请注意以下事项
ZipArchive.Dispose()
除非您使用
ZipArchive(Stream,?ZipArchiveMode,?Boolean)构造函数重载构造对象并将其leaveOpen参数设置为true,否则所有底层流都将关闭并且不再可用于后续写入操作。当您使用完 的此实例时
ZipArchive,调用Dispose()以释放此实例使用的所有资源。您应该消除对该ZipArchive实例的进一步引用,以便垃圾收集器可以回收该实例的内存,而不是让它保持活动状态以进行终结。
并且由于您想继续使用内存流,因此您需要确保它保持打开状态并且流指针已重置,以便可以从头开始读取。
public async Task<IHttpActionResult> ExportReport(int id, ReportModel report) {
try {
var result = await ReportGenerationService.ExportReportForId(id, report.Page, report.PageSize, report.SortField, report.SortDir, report.SearchTerm, report.StartDate, report.EndDate, report.UserId, report.TeamId, report.SelectedDateItem);
if (result != null) {
var compressedFileStream = new MemoryStream();
using(var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create,
leaveOpen: true)) { //<--This is important to keep stream open
//Create a zip entry for each attachment
var zipEntry = zipArchive.CreateEntry("textExport.csv");
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(result.ExportToBytes()))
using (var zipEntryStream = zipEntry.Open()) {
//Copy the attachment stream to the zip entry stream
await originalFileStream.CopyToAsync(zipEntryStream);
}
}// disposal of archive will force data to be written/flushed to memory stream.
compressedFileStream.Position = 0;//reset memory stream position.
var response = new HttpResponseMessage(HttpStatusCode.OK) {
Content = new StreamContent(compressedFileStream)
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {
FileName = "Export.zip"
};
return ResponseMessage(response);
}
return NotFound();
} catch (Exception ex) {
return InternalServerError(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
你错过了一些using(){}块。
确保按正确顺序关闭 originalFileSteam、zipEntryStream 和 zipArchive。
并且可以肯定的是,重置 memoryStream。我不知道这是否需要,但它不会受到伤害。
//using (var compressedFileStream = new MemoryStream())
var compressedFileStream = new MemoryStream();
using (var zipArchive = new ZipArchive(...))
{
//Create a zip entry for each attachment
var zipEntry = zipArchive.CreateEntry("textExport.csv");
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(result.ExportToBytes()))
using (var zipEntryStream = zipEntry.Open())
{
//Copy the attachment stream to the zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
}
//compressedFileStream .Position = 0;
var responseBytes =new MemoryStream(compressedFileStream.ToArray());
var response = new HttpResponseMessage(HttpStatusCode.OK) {Content = new StreamContent(responseBytes )};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return ResponseMessage(response);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4104 次 |
| 最近记录: |