MemoryStream 到 HttpResponseMessage
Posted
技术标签:
【中文标题】MemoryStream 到 HttpResponseMessage【英文标题】:MemoryStream to HttpResponseMessage 【发布时间】:2017-07-16 00:53:20 【问题描述】:我在服务器上生成了一个 Pdf,需要将其作为响应返回给我的 Web 客户端,以便我得到一个“另存为”对话框。
生成 pdf,并保存到内存流...然后返回到我的方法,该方法将返回 HttpResponseMessage。
方法是:
[Route("GeneratePdf"), HttpPost]
public HttpResponseMessage GeneratePdf(PlateTemplateExtendedDto data)
var doc = GeneratePdf(DataForThePdf);
//using (var file = File.OpenWrite("c:\\temp\\test.pdf"))
// doc.CopyTo(file); // no need for manual stream copy and buffers
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
byte[] buffer = new byte[0];
//get buffer
buffer = doc.GetBuffer();
//content length for use in header
var contentLength = buffer.Length;
response.Headers.AcceptRanges.Add("bytes");
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(doc);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("render");
response.Content.Headers.ContentDisposition.FileName = "yes.pdf";
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentLength = doc.Length;
return response;
但是,文档呈现为空白文件,虽然它具有文件大小和我创建的文档的属性(如果文件属性没问题,则为 pdf 信息,以及页面宽度和高度),但文档显示为空白。
如果我取消注释被注释掉的代码,以保存在本地,则该文件是完美的。文件大小为 228,889 字节。但是,当我让它转到我的网页并保存时,它是 405,153 字节,文件名是“未定义”。
如果我断点,我会看到这些结果:
在前端脚本中,我这样处理下载的对象:
$.post("/api/PlateTemplate/GeneratePdf", data).done(function (data, status, headers)
// headers = headers();
var filename = headers['x-filename'];
var contentType = headers['content-type'];
//Create a url to the blob
var blob = new Blob([data], type: contentType );
var url = window.URL.createObjectURL(blob);
var linkElement = document.createElement('a');
linkElement.setAttribute('href', url);
linkElement.setAttribute("download", filename);
//Force a download
var clickEvent = new MouseEvent("click",
"view": window,
"bubbles": true,
"cancelable": false
);
linkElement.dispatchEvent(clickEvent);
);
我不确定文件损坏的位置。我做错了什么?
编辑:按照建议使用以下代码:
$.post("/api/PlateTemplate/GeneratePdf", data).done(function (data, status, headers)
alert(data.length);
var xhr = new XMLHttpRequest();
$("#pdfviewer").attr("src", URL.createObjectURL(new Blob([data],
type: "application/pdf"
)))
.net代码:
var doc = GeneratePdf(pdfParams);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK);
byte[] buffer = new byte[0];
//get buffer
buffer = doc.ToArray();
//content length for use in header
var contentLength = buffer.Length;
response.Headers.AcceptRanges.Add("bytes");
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(doc);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("render");
response.Content.Headers.ContentDisposition.FileName = "yes.pdf";
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentLength = doc.Length;
return response;
看来我正在丢失数据。 在我从调用中取回数据后,警报是我的 javascript 中“data.length”的长度。 文件属性为原始pdf文件信息。
从 api 发送的文件,大小为 227,564,如果我保存它,它与磁盘上的字节大小匹配。所以看起来发送是可以的。但是在javascript大小上,当我读入文件时,它是424946,当我这样做时: var file = new Blob([data], type: 'application/pdf' ); (其中 data 是来自服务器的响应)。
【问题讨论】:
使用doc.ToArray()
而不是doc.GetBuffer()
jQuery ajax 默认不处理二进制数据Displaying pdf from arraybuffer,另见How to build PDF file from binary string returned from a web-service using javascript
@L.B 和 Guest - 我已经尝试了您的两个想法,并编辑了我的问题。似乎我在某处丢失了一些数据.... PDF 正在尝试渲染,但我的字节数不足,所以文件似乎以某种方式被截断?我已将详细信息添加到问题的末尾。
尝试了你们所说的所有内容以及更多内容。从 api 发送的文件,大小为 227,564,如果我保存它,它与磁盘上的字节大小相匹配。所以看起来发送是可以的。但是在javascript大小上,当我读入文件时,它是424946,当我这样做时: var file = new Blob([data], type: 'application/pdf' ); (其中数据是来自服务器的响应)。
【参考方案1】:
ContentLength 设置看起来有些可疑(不是结果):
//content length for use in header
var contentLength = buffer.Length;
response.Content.Headers.ContentLength = doc.Length;
【讨论】:
我将 doc.Length 更改为 contentLength,但得到了相同的结果。大小差异不同,但仍小于应有的大小。【参考方案2】:我通过使用从 .Net 控制器到 javascript web api 调用结果的 base64 编码字符串“修复”了这个问题,然后允许浏览器通过指定类型('application/pdf')将其转换为二进制。
【讨论】:
以上是关于MemoryStream 到 HttpResponseMessage的主要内容,如果未能解决你的问题,请参考以下文章
将 iTextSharp 文档加载到 MemoryStream