C# 读取二进制文件并使用 Response.BinaryWrite()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/848679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading a binary file and using Response.BinaryWrite()
提问by jhunter
I have an app that needs to read a PDF file from the file system and then write it out to the user. The PDF is 183KB and seems to work perfectly. When I use the code at the bottom the browser gets a file 224KB and I get a message from Acrobat Reader saying the file is damaged and cannot be repaired.
我有一个应用程序需要从文件系统读取 PDF 文件,然后将其写给用户。PDF 为 183KB,似乎运行良好。当我使用底部的代码时,浏览器会得到一个 224KB 的文件,并且我从 Acrobat Reader 收到一条消息,说该文件已损坏且无法修复。
Here is my code (I've also tried using File.ReadAllBytes(), but I get the same thing):
这是我的代码(我也尝试过使用 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);
}
采纳答案by BarneyHDog
Try adding
尝试添加
Response.End();
Response.End();
after the call to Response.BinaryWrite().
在调用 Response.BinaryWrite() 之后。
You may inadvertently be sending other content back after Response.BinaryWrite which may confuse the browser. Response.End will ensure that that the browser only gets what you really intend.
您可能会在 Response.BinaryWrite 之后无意中发送回其他内容,这可能会混淆浏览器。Response.End 将确保浏览器只获取您真正想要的内容。
回答by Igor Zelaya
Maybe you are missing a Response.close to close de Binary Stream
也许你错过了一个 Response.close 来关闭二进制流
回答by AJ.
In addition to Igor's Response.Close(), I would add a Response.Flush().
除了 Igor 的 Response.Close(),我还要添加一个 Response.Flush()。
回答by Robin Day
We've used this with a lot of success. WriteFile do to the download for you and a Flush / End at the end to send it all to the client.
我们已经成功地使用了它。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();
回答by jinsungy
Response.BinaryWrite(bytes);
Response.Flush();
Response.Close();
Response.End();
This works for us. We create PDFs from SQL Reporting Services.
这对我们有用。我们从 SQL Reporting Services 创建 PDF。
回答by LukeH
Since you're sending the file directly from your filesystem with no intermediate processing, why not use Response.TransmitFile
instead?
既然您直接从文件系统发送文件而没有中间处理,为什么不Response.TransmitFile
改用呢?
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition",
"attachment; filename=\"" + Path.GetFileName(path) + "\"");
Response.TransmitFile(path);
Response.End();
(I suspect that your problem is caused by a missing Response.End
, meaning that you're sending the rest of your page's content appended to the PDF data.)
(我怀疑您的问题是由丢失的 引起的Response.End
,这意味着您正在发送附加到 PDF 数据的页面内容的其余部分。)
回答by Faisal
Please read this before using Response.TransmitFile: http://improve.dk/blog/2008/03/29/response-transmitfile-close-will-kill-your-application
请在使用 Response.TransmitFile 之前阅读此内容:http: //improve.dk/blog/2008/03/29/response-transmitfile-close-will-kill-your-application
回答by extremeandy
I also found it necessary to add the following:
我还发现有必要添加以下内容:
Response.Encoding = Encoding.Default
If I didn't include this, my JPEG was corrupt and double the size in bytes.
如果我不包括这个,我的 JPEG 就会损坏并且以字节为单位的大小加倍。
But only if the handler was returning from an ASPX page. It seemed running from an ASHX this was not required.
但前提是处理程序从 ASPX 页返回。它似乎是从 ASHX 运行的,这不是必需的。
回答by Nils
Just for future reference, as stated in this blog post: http://blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback-helps-us-improve-msdn-documentation.aspx
仅供将来参考,如本博客文章所述:http: //blogs.msdn.com/b/aspnetue/archive/2010/05/25/response-end-response-close-and-how-customer-feedback- help-us-improve-msdn-documentation.aspx
It is notrecommended to call Response.Close()
or Response.End()
- instead use CompleteRequest()
.
这是不推荐打电话Response.Close()
或Response.End()
-改用CompleteRequest()
。
Your code would look somewhat like this:
你的代码看起来有点像这样:
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();
回答by Mr Zachary
In my MVC application, I have enabled gzip compression for all responses. If you are reading this binary write from an ajax call with gzipped responses, you are getting the gzipped bytearray rather than original bytearray that you need to work with.
在我的 MVC 应用程序中,我为所有响应启用了 gzip 压缩。如果您从带有 gzipped 响应的 ajax 调用中读取此二进制写入,您将获得 gzipped 字节数组,而不是您需要使用的原始字节数组。
//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 }); " This will give you that invalid/corrupt file that you are trying to open when you turn that byte array into a file in your javascript if you don't uncompress it first.
" var blob = new Blob([response.data], { type: type }); " 这会给你那个无效/损坏的文件,当你把那个字节数组转换成你的javascript中的文件时,如果你先不要解压。
To fix this, you have a choice to either prevent gzipping this binary data so that you can properly turn it into the file that you are downloading, or you have to decompress that gzipped data in your javascript code before you turn it into a file.
要解决此问题,您可以选择阻止对二进制数据进行 gzip 压缩,以便您可以正确地将其转换为您正在下载的文件,或者您必须在将其转换为文件之前在 javascript 代码中解压缩该 gzip 数据。