Click here to Skip to main content
15,123,118 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, 

I have a pdf file of type byte array. I need to download / open the same as pdf in clients machine. 
I tried to achieve the same by adding response headers for content-disposition but not successful. In browser I see something like bytes.

I am not getting any clue of what is happening here. Do anyone has idea on how to achieve this. Thanks in advance!

In Browser I see like:

<pre>%PDF-1.6 %���� 1 0 obj << /Filter/FlateDecode /Length 62778 /Subtype/OpenType >> stream H�\�t���M<y��X�i|ӂi���Ǵ�:�n��X� C�����=�u�ĭ�`8@4k���R@��F�z܌��N�9�f3 rB�>�D��r���gq����<�(@D)m6#Z�܌��CɨfZ�ܮV��<ҵ�Z�}��1���]]]S<�G�{��/w�@����0P�z�>�?Ŏ�A1(��<f�9�� �A��V�;�փ����8.���� w y���D����H=�iEV



What I have tried:

Code I Tried:

                   //Here I am writing the bytes as File and store in the path - It is successful

                    byte[] bytes;
                    MemoryStream ms = new MemoryStream(pdfFile); //pdfFile is of type Byte[]
                    bytes = ms.ToArray();
                    File.WriteAllBytes(@"C:\inetpub\wwwroot\s92.dev.local\TestForm.pdf", bytes);

                  //Here I am trying to download the file - It is not successful, I am seeing somehting like bytes as shown in image above
                    var response = HttpContext.Current.Response;
                    response.Clear();
                    response.ClearHeaders();
                    response.ClearContent();
                    response.ContentType = "application/pdf";
                    response.AppendHeader("Content-Disposition", "attachment; filename=MyFile.pdf");
                    response.TransmitFile(HttpContext.Current.Server.MapPath("~/TestForm.pdf"));
                    response.End();
Posted
Updated 3-Aug-21 4:26am
v2

1 solution

That's some very confused code: you have a byte array, so you copy it to a MemoryStream, then copy the MemoryStream to another byte array, and then write that third copy of the data to a local file, before sending the local file back to the client.

You could simply write the original byte array to the file before sending it:
C#
string path = Server.MapPath("~/TestForm.pdf");
File.WriteAllBytes(path, pdfFile);

However, remember that multiple users could be accessing your site at the same time. If two users request a PDF download at the same time, you will be overwriting the file for one user with the data for another. This could lead to corrupted downloads, or to your site exposing confidential information to unauthorized users.

A better solution would be to simply write the byte array directly to the response, bypassing the file system.
C#
response.Clear();
response.ContentType = "application/pdf";
response.AppendHeader("Content-Disposition", "attachment; filename=\"MyFile.pdf\"");
response.OutputStream.Write(pdfFile);
response.End();
   
Comments
Indhu S 2021 3-Aug-21 10:29am
   
Thanks much for the response. Sorry for the confusion, the first block I just tried to see whether it is at least getting saved in file system. Also I unnecessarily converting the types back and forth.

Leaving that part, I tried to directly write the byte array by following your code

var response = HttpContext.Current.Response;
response.Clear();
response.ContentType = "application/pdf";
response.AppendHeader("Content-Disposition", "attachment; filename=\"MyFile.pdf\"");
response.OutputStream.Write(pdfFile, 0, pdfFile.Length);
response.End();


But my browser output is still the same. I also tried with response.BinaryWrite(pdfFile) but no luck..

Can you share some light?
Richard Deeming 3-Aug-21 11:21am
   
That would suggest your Content-Disposition and Content-Type headers aren't reaching the browser, or the browser is ignoring them for some reason.

Check the network request in your browser's developer tools to make sure the headers are as expected.
Indhu S 2021 4-Aug-21 11:52am
   
Thanks for the response Richard!
I am seeing the response headers as given below in network tab though. So really not sure what is going wrong.

cache-control: private
content-disposition: attachment; filename="MyFile.pdf"
content-type: application/pdf
date: Wed, 04 Aug 2021 15:40:19 GMT
server: Microsoft-IIS/10.0
Richard Deeming 4-Aug-21 12:35pm
   
The headers look correct. There must be something odd with your browser. Can you try a different browser?
Indhu S 2021 5-Aug-21 2:01am
   
Thanks again for your response. Yes, I tried that already and could see the same behavior across all browser(Chrome/Firefox and Edge) :(
Richard Deeming 5-Aug-21 4:35am
   
That's very odd. The content you're seeing in the browser is definitely a PDF file, but it's as if the browser is ignoring both the content-disposition and content-type headers, and trying to display it as a text file.

Are you able to open PDF files from other sites? For example:
https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf[^]

Are there any other headers in the response which might affect it?
Indhu S 2021 5-Aug-21 9:45am
   
Yes. I am able to view other PDF's perfectly in browser. Thank you so much Richard for constant responses. I highly appreciate that and hearty thanks for the same. I just wanted to know whether these are the only steps(or code) to download a PDF.
If that is right, there is certainly something else I should check these with overall project structure(some headers/classes or something else from other calls) affecting this.
Richard Deeming 5-Aug-21 9:52am
   
The only other thing I can think of - are you issuing the request in an unusual way? For example by making an AJAX call?

If you're just clicking a link or button on the page, then are you able to share the full request and response headers (after removing any sensitive data, obviously)?
Indhu S 2021 8-Aug-21 8:22am
   
Hi Richard, Thanks for the comment.
Posting the request and response headers below. Have marked some values as "XXXXX". It is not an ajax call, but I am actually trying to download a pdf on the custom submit action of the Sitecore Forms module.

One error I used to get is that ,
"System.Web.HttpException: 'Server cannot append header after HTTP headers have been sent."
in the @Html.AntiForgeryToken() line of Forms.cshtml.

Response Headers:

cache-control: private
content-disposition: attachment; filename="MyFile.pdf"
content-type: application/pdf
date: Fri, 06 Aug 2021 14:21:15 GMT
server: Microsoft-IIS/10.0



Request headers:

:authority: XXXXXXXXXX.sc.XXXXXXXX-intra.com
:method: POST
:path: /formbuilder?fxb.FormItemId=XXXXXXXXXXXXX&fxb.HtmlPrefix=fxb.XXXXXXXXXXXXXX
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en,en-US;q=0.9,ar;q=0.8
content-length: 3342
content-type: application/x-www-form-urlencoded; charset=UTF-8
cookie: XXXXXXXXXXXXXRoleCookie=XXXXXXXXXX; OptanonAlertBoxClosed=2021-07-27T12:49:52.228Z;
_gcl_au=XXXXXXXXXXXXXXXX;
_ga=XXXXXXXXXXXXXXX; Disclaimer_cookie=true;
SC_ANALYTICS_GLOBAL_COOKIE=7XXXXXXXXXXXXXXX|True;
ASP.NET_SessionId=XXXXXXXXXXXXXXXXX;
FormsAuthKey=1;
__RequestVerificationToken=VXXXXXXXXXXXXXXXXXxx;
_gid=XXXXXXXXXXXXXXXXX;
OptanonConsent=isGpcEnabled=0&datestamp=Fri+Aug+06+2021+12%3A53%3A19+GMT%2B0530+(India+Standard+Time)
&version=6.20.0&isIGlobal=false&hosts=&consentId=XXXXXXXXXXXXXxx&
interactionCount=1&landingPath=NotLandingPage
&groups=1%3A1%2C2%3A1%2C3%3A1%2C4%3A1&
geolocation=%3B&AwaitingReconsent=false;
countryXX#lang=en
origin: https://XXXXX.sc.XXXXXXX-intra.com
referer: https://XXXXXXXX.sc.XXXXXXXX-intra.com/en/testformspdf
sec-ch-ua: "Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"
sec-ch-ua-mobile: ?0
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-origin
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36
x-requested-with: XMLHttpRequest
Richard Deeming 9-Aug-21 3:06am
   
Using an XMLHttpRequest to download a file is more complicated than just clicking a link or submitting a form.

Can you share the Javascript code you're using? It should look similar to the code in this SO answer[^].
Indhu S 2021 10-Aug-21 4:26am
   
Hi Richard, Unfortunately I was not able to share the Jquery as it is from Sitecore side and it has licensing issues. But you gave me an great hint about XMLHttpRequest, let me check further on this one. Thank you so much for all the prompt and highly helpful responses.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900