我有一个应用需要从文件系统中读取PDF文件,然后将其写出给用户。 PDF是183KB,似乎完美无缺。当我使用底部的代码时,浏览器获取一个224KB的文件,我从Acrobat Reader收到一条消息,说文件已损坏且无法修复。
这是我的代码(我也尝试过使用File.ReadAllBytes(),但我得到同样的东西):
using (FileStream fs = File.OpenRead(path))
{
int length = (int)fs.Length;
byte[] buffer;
using (BinaryReader br = new BinaryReader(fs))
{
buffer = br.ReadBytes(length);
}
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", String.Format("attachment;filename={0}", Path.GetFileName(path)));
Response.ContentType = "application/" + Path.GetExtension(path).Substring(1);
Response.BinaryWrite(buffer);
}
答案 0 :(得分:23)
尝试添加
到Response.End();
调用Response.BinaryWrite()。
之后您可能无意中在Response.BinaryWrite之后发回其他内容,这可能会混淆浏览器。 Response.End将确保浏览器仅获得您真正想要的内容。
答案 1 :(得分:16)
Response.BinaryWrite(bytes);
Response.Flush();
Response.Close();
Response.End();
这对我们有用。我们从SQL Reporting Services创建PDF。
答案 2 :(得分:7)
我们已经使用了很多成功。 WriteFile为您下载,并在最后将Flush / End发送给客户端。
//Use these headers to display a saves as / download
//Response.ContentType = "application/octet-stream";
//Response.AddHeader("Content-Disposition", String.Format("attachment; filename={0}.pdf", Path.GetFileName(Path)));
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", String.Format("inline; filename={0}.pdf", Path.GetFileName(Path)));
Response.WriteFile(path);
Response.Flush();
Response.End();
答案 3 :(得分:5)
由于您是直接从文件系统发送文件而没有中间处理,为什么不使用Response.TransmitFile
呢?
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition",
"attachment; filename=\"" + Path.GetFileName(path) + "\"");
Response.TransmitFile(path);
Response.End();
(我怀疑您的问题是由于缺少Response.End
造成的,这意味着您将页面的其余内容发送到PDF数据中。)
答案 4 :(得分:4)
不建议致电Response.Close()
或Response.End()
- 而是使用CompleteRequest()
。
您的代码看起来有点像这样:
byte[] bytes = {};
bytes = GetBytesFromDB(); // I use a similar way to get pdf data from my DB
Response.Clear();
Response.ClearHeaders();
Response.Buffer = true;
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + anhangTitel);
Response.AppendHeader("Content-Length", bytes.Length.ToString());
this.Context.ApplicationInstance.CompleteRequest();
答案 5 :(得分:2)
请在使用Response.TransmitFile:http://improve.dk/blog/2008/03/29/response-transmitfile-close-will-kill-your-application
之前阅读此内容答案 6 :(得分:1)
也许你错过了关闭de Binary Stream的Response.close
答案 7 :(得分:1)
在我的MVC应用程序中,我为所有响应启用了gzip压缩。如果您正在使用gzip响应从ajax调用中读取此二进制写入,则需要使用gzip压缩的bytearray而不是需要使用的原始bytearray。
//c# controller is compressing the result after the response.binarywrite
[compress]
public ActionResult Print(int id)
{
...
var byteArray=someService.BuildPdf(id);
return return this.PDF(byteArray, "test.pdf");
}
//where PDF is a custom actionresult that eventually does this:
public class PDFResult : ActionResult
{
...
public override void ExecuteResult(ControllerContext context)
{
//Set the HTTP header to excel for download
HttpContext.Current.Response.Clear();
//HttpContext.Current.Response.ContentType = "application/vnd.ms-excel";
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("content-disposition", string.Concat("attachment; filename=", fileName));
HttpContext.Current.Response.AddHeader("Content-Length", pdfBytes.Length.ToString());
//Write the pdf file as a byte array to the page
HttpContext.Current.Response.BinaryWrite(byteArray);
HttpContext.Current.Response.End();
}
}
//javascript
function pdf(mySearchObject) {
return $http({
method: 'Post',
url: '/api/print/',
data: mySearchObject,
responseType: 'arraybuffer',
headers: {
'Accept': 'application/pdf',
}
}).then(function (response) {
var type = response.headers('Content-Type');
//if response.data is gzipped, this blob will be incorrect. you have to uncompress it first.
var blob = new Blob([response.data], { type: type });
var fileName = response.headers('content-disposition').split('=').pop();
if (window.navigator.msSaveOrOpenBlob) { // for IE and Edge
window.navigator.msSaveBlob(blob, fileName);
} else {
var anchor = angular.element('<a/>');
anchor.css({ display: 'none' }); // Make sure it's not visible
angular.element(document.body).append(anchor); // Attach to document
anchor.attr({
href: URL.createObjectURL(blob),
target: '_blank',
download: fileName
})[0].click();
anchor.remove();
}
});
}
“var blob = new Blob([response.data],{type:type});” 这将为您提供在将该字节数组转换为javascript中的文件时尝试打开的无效/损坏文件(如果您不首先解压缩它)。
要解决此问题,您可以选择阻止对此二进制数据进行gzipping,以便您可以将其正确地转换为正在下载的文件,或者在将其转换为javascript代码之前必须将其解压缩。一个文件。
答案 8 :(得分:0)
除了Igor的Response.Close()之外,我还要添加一个Response.Flush()。
答案 9 :(得分:0)
我还发现有必要添加以下内容:
Response.Encoding = Encoding.Default
如果我没有包含这个内容,我的JPEG就会损坏并且会以字节大小加倍。
但仅当处理程序从ASPX页面返回时。它似乎从ASHX运行,这不是必需的。