I had a method to populate PDF in browsers. It can have PDF be shown in the browsers perfectly. However after I clicked "SAVE" bottom, and open the downloaded file from my local, it shows
"Adobe Reader could not open 'xxx.pdf' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded)."
Below is my code
public static void PopulatePDF(byte[] PDFcontents)
{
var response = HttpContext.Current.Response;
response.AppendHeader("Content-Disposition", "inline; filename=xxx.pdf");
response.AppendHeader("Content-Length", PDFcontents.Length.ToString());
response.AppendHeader("Content-Transfer-Encoding", "binary");
response.OutputStream.Write(PDFcontents,0,contents.PDFcontents);
response.BufferOutput = true;
response.Buffer = true;
response.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
response.BinaryWrite(PDFcontents);
response.Flush();
response.End();
}
The method did pass data (byte[2100217]) and display the pdf in the browser. But the tricky part is that it couldn't be opened from the downloaded file at local after "Save" was used.
Not sure what happened in between. Is this due to the version of Adobe Reader I'm using? It's Adobe Reader XI (version 11.0.10).
Related
I inherited an .net application that allows users to download a pdf. Now, I am able to download the pdf file when I run locally but when I deploy to IIS server I run into problems. The download works on Firefox but doesnt work on Chrome, and sometimes on IE. The fact that I can download it on my local development environment tells that it could be something with IIS configuration or maybe my code. The pdf is stored in ms sql server 2012 table as varbinary. I provided some code below that is used to read the data. Please let me know if there are other information you all need. Also, I checked the iis logs and I am getting 200 status codes for everything. Nothing stands out in there.
if(Session["DetailID"] != null)
{
//get the file
DataTable dt = sp_Attachment_Download(lblAttachmentIDD.Text);
DataRow row = dt.Rows[0];
string name = (string)row["AFileName"];
string contentType = (string)row["AFileType"];
Byte[] data = (Byte[])row["AFile"];
/// Send the file to the browser
Response.AddHeader("Content-type", contentType);
Response.AddHeader("Content-Disposition", "attachment; filename=" + name);
Response.BinaryWrite(data);
Response.Flush();
Response.Close();
}
EDITED----------
I am using the developer tools for IE and Chrome and found something interesting. Chrome gives me the following error when I click on the link:
interpreted as Document but transferred with MIME type application/pdf:
IE doesnt give an error but something caught my attention. I my REQUEST header, ACCEPT does not contain application/pdf and the RESPONSE Content-Type has application/pdf. Could this be something? How can I set the ACCEPT to include application/pdf in aspx page?
I had kinda similar issue when downloading pdf from chrome as in my case filename had a comma in it and that chrome apparently didn't like it, so I removed comma from filename and it worked.
PS: Please try not to use Response.Close(). It aborts the thread and throws exception.
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=" + fileName.Replace(",",,");
Response.CacheControl = "No-cache";
Response.Write(data);
Response.Flush();
Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
Maybe this will help, here's my code to do the same thing. One thing that I noticed is that you're not specifying the file length, which I believe is required. Please note that pFileData is class that contains FileName, a string, and FileData, a byte[].
System.Web.HttpResponse Response = System.Web.HttpContext.Current.Response;
Response.Clear();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment;filename=" + pFileData.FileName);
Response.AddHeader("Content-Length", pFileData.FileData.Length.ToString());
Response.BufferOutput = false;
Response.BinaryWrite(pFileData.FileData);
Response.Flush();
Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
Response.End();
I tried to get a pdf file opened in chrome but it seems to be stuck in the middle of somewhere during displaying process. The code seems to work because it can get PDF opened in IE, not sure why it got stuck in chrome. The screen will just grey out, show the "LOADING" sign, and stop at 7/8. The file is around 6MB or more.
public static void ReturnPDF(byte[] contents)
{
var response = HttpContext.Current.Response;
response.Clear();
response.AppendHeader("Content-Disposition", "inline;filename=" + "abc.pdf");
response.BufferOutput = true;
response.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
response.BinaryWrite(contents);
response.Flush();
response.Close();
response.End();
}
Any thoughts? Thanks
[UPDATE]
I tried firefox with version 30.0 and it WORKS. My IE is 8.0.7601.17514, which can also open pdf. My Chrome is 39.0.2171.95. Not sure wheather the version of the browser matters or not, here only chrome fails to open the inline PDF...
[SOLVED]
After adding content-length, chrome can open the inline PDF.
public static void ReturnPDF(byte[] contents)
{
var response = HttpContext.Current.Response;
response.Clear();
response.AppendHeader("Content-Disposition", "inline;filename=" + "abc.pdf");
//After adding Content-Length, chrome is able to open PDF inline
response.AppendHeader("Content-Length", contents.Length.ToString());
response.BufferOutput = true;
response.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
response.BinaryWrite(contents);
response.Flush();
response.Close();
response.End();
}
The OP's original code created the response like this:
response.Clear();
response.AppendHeader("Content-Disposition", "inline;filename=" + "abc.pdf");
response.BufferOutput = true;
response.ContentType = System.Net.Mime.MediaTypeNames.Application.Pdf;
response.BinaryWrite(contents);
response.End();
This code especially does not set the Content-Length header. Some web browser versions (not only Chrome but also certain versions of other browsers) without that header tend to prematurely consider the download finished.
Detecting when a download is finished on a connection initially created as persistent, may not be trivial if neither a non-identity Transfer-Encoding nor a Content-Length has been supplied.
Thus, the solution here is to add
response.AppendHeader("Content-Length", contents.Length.ToString());
before writing the contents.
Try with "Content-disposition: attachment" header.
Thanks mkl's suggestions.
I added the content length in the header and the pdf can be successfully opened in Chrome!
I have a byte array in the database and i need to show that in a pdf file format. Here is the way i did that. However, this doesn't work on Android tablets(checked in 2.3.5 and 3.2).
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.BufferOutput = true;
Response.Buffer = false;
Response.AddHeader("Content-Length", binaryData.Length.ToString());
Response.AppendHeader("Content-Disposition", "inline;filename=ClientDocument.PDF");
// Response.BinaryWrite(binaryData);
Response.OutputStream.Write(binaryData, 0, binaryData.Length);
Response.End();
Can you guys think of any way i could make it work on all the browsers?
Appreciate the help
Thanks
Couple of things...
Change the content type to correct mime-type of PDF files. There are vast array of these in use application/pdf, application/x-pdf, application/acrobat, applications/vnd.pdf, text/pdf, text/x-pdf", we just use application/pdf.
Response.ContentType = "application/pdf";
Then if you want the browser to open and display the PDF file, remove the Content-Disposition header.
... or ... if you want the browser to download the PDF file change the Content-Disposition type to "attachment" rather than "inline".
Response.AppendHeader("Content-Disposition", "attachment;filename=ClientDocument.PDF");
Have you upgraded to latest version of Android on the test tablets/phones?
That fixed it for me when I had a similar problem (PDFs not opening or downloading when sent to browser from stream or byte[] on Android only).
basically below is the code for me to read pdf file, the output for this code below is ask client to download the pdf file and open it from client side, this is not what i want,what i want it open the pdf at another browswer windows or open in inside tag under same browser windows, but how can i make it?
var fi = new FileInfo(Server.MapPath(#"~/AIA2.pdf"));
Response.Clear();
Response.AddHeader("Content-Disposition",
String.Format("attachment; filename=\"{0}\"",
"AIA2.pdf"));
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.WriteFile(fi.FullName);
Response.End();
This is not upto the server to decide how content is handled - content disposition could be set to attachment or inline but its to the handling application to process these and i do not think any browser does that.
I can suggest a two step solution for this:
Use inline; instead of attachment
On the client side (if you have control on that ofcourse), use something like
That should do the trick!
Im using ssrs through a reports server to generate a resultStream byte array using ReportExecutionService.Render() which I am currently serving to the user with the following code. Is there a way I can use this same byte array to automatically open the report in a new browser window instead of going to the save/open dialog?
public void RenderReport (byte[] reportDigits, ReportItem reportItem)
{
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.ContentType = reportItem.ReportMimeType;
response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", reportItem.ExportName));
response.OutputStream.Write(reportDigits, 0, reportDigits.Length);
response.End();
}
In the past I have used a separate ReportViewer.aspx page that I would open first then display the report but would like to do it all in code behind if that is possible.
Thanks
It's this line:
response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", reportItem.ExportName));
Thats causing it to be downloaded. Comment out that line, and as long as the browser can handle the mime type, it will render in the browser window.
Simply change the Header that you are adding to something other than an attachement. Make it the format of your data--and hopefully the browser will recognize it.