Fetch word document from an API and download it - c#

I have a 3rd party API. When i call that api it will output a word document.
In my .net website i have an ASPX page. When user browse that page, i have to call that 3rd party API, get the word document and should send it to user as a downloadable word document.
Note: I cannot call that 3rd party api using javascript for security reasons.
I tried below code
WebClient wClient = new WebClient();
var pagesource = wClient.DownloadString("3rd party api");
Response.Clear();
Response.AddHeader("Content-Type", "application/msword");
Response.AddHeader("Content-Disposition", "attachment; filename=test.docx");
Response.Write(pagesource);
Response.End();
It downloads the word document. But when i open it, it is corrupted.

I believe wClient.DownloadString is going to download the document as a string. You want to use .DownloadData to get the data as a byte array (binary). And then something like:
var fileBytes = wClient.DownloadData("3rd party api");;
if (fileBytes == null) return;
string filename = DateTime.Now.ToString("yyyy-MM-dd") + "-filename.docx";
Response.Clear();
Response.AddHeader("Content-Length", fileBytes.Length.ToString(CultureInfo.InvariantCulture));
//Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", filename)); // save file as attachment
Response.AddHeader("Content-Disposition", string.Format("inline; filename={0}", filename)); // display inline in browser
Response.AddHeader("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
Response.BinaryWrite(fileBytes);
Response.Flush();
Response.End();

Pretty sure your mime type is incorrect for docx. You are using the one for .doc.
Try
Response.AddHeader("Content-Type", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");

Related

IE11 not respecting filename of content-disposition

My code is opening a PDF in a tab/new window using an .apsx page and the following code:
string fileName = GetFileName(so);
Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "inline; filename=" + fileName);
Response.BinaryWrite(pdfStream);
When selecting the save option in the browser for the PDF, the filename in the save dialogue is not being populated correctly in IE (11); it's still using the page name. Chrome and FF are working like I'd expect them too (using the provided filename as the suggested name).
In addition, IE works the same as Chrome and FF when i change the content-disposition to attachment instead of inline. They all use the filename as the suggested save name.
Am I missing something in how to use the inline functionality?
Did you try change inline to attachment ?
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);

HTML to PDF conversion - Almost works, but

I spent a good part of last few days searching for easy-to-use library that takes a html string as input, and produces PDF output as a file to the client browser.
Of the few dozen tools I tried out, a product called NReco PDF Generator, which is one of many derivative tools based on wkhtmltopdf, seems to suit my needs.
Here's my test code:
var strHtml = String.Format("<h1>Hello World!</h1");
Response.Clear();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=test.pdf");
(new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(strHtml, null, Response.OutputStream);
Response.End();
With the above code, I expected to see a PDF file being passed to my browser. Instead, I only see the output stream being generated in my developer console. (BTW, I'm using Chrome)
My question is NOT about how the said product works, which I think is working as intended, but it is about whether my code is missing any action for the .NET's Response object or is doing anything wrong. As I already indicated, I can see the converted Pdf stream in the console. I think it's just a matter of capturing that stream in a file and passing it to the client.
The missing line is Response.BinaryWrite(pdfBytes). Without that line the PDF will not be rendered to the user.
As far as I can tell you do not need the lines:
Response.Clear();
Response.ClearHeaders();
The following works for me (Obviously, you need to add using NReco.PdfGenerator;)
string strHtml = String.Format("<h1>Hello World!</h1");
HtmlToPdfConverter pdfConverter = new HtmlToPdfConverter();
var pdfBytes = pdfConverter.GeneratePdf(strHtml);
Response.ContentType = "application/pdf";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.AddHeader("Content-Disposition", "Inline; filename=TEST.pdf");
Response.BinaryWrite(pdfBytes);
Response.Flush();
Response.End();
Store the PDF as a byte array, then write it to the response.
var pdfBytes = new NReco.PdfGenerator.HtmlToPdfConverter().GeneratePdf(strHtml);
Response.BinaryWrite(pdfBytes);
instead of
(new NReco.PdfGenerator.HtmlToPdfConverter()).GeneratePdf(strHtml, null, Response.OutputStream);
Inspiration for this taken from NReco's site.

Save download file dialog

I have created a PDF using iText and storing it in a particular location (specified in the code). I would like to prompt a save dialog box for the user to choose location on his computer to save the pdf. I checked iText tutorial but it didn't help me.
Here is the code for generating the PDF file:
Document objDoc = new Document();
PdfWriter.GetInstance(objDoc, new FileStream("C:\\HelloWorld.pdf", FileMode.Create));
objDoc.Open();
objDoc.Add(new Paragraph("welcome iText Pdf"));
objDoc.Close();
I tried like this for saving:
string FileName ="HelloWorld.pdf";
String FilePath = #"C:\";
HttpResponse response = HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "application/pdf";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath + FileName);
response.Flush();
response.End();
I'm assuming you're doing this from a web page since you tagged this ASP.NET. You need to add the Content-Disposition header. See the following question for details:
Force download of a file on web server - ASP .NET C#

How can you force the browser to download an xml file?

This is my problem.
I load xml from my database and push it to the client using code.
But the problem is that the browser automatically opens that xml instead of offering it as a download.
Is there a way to force your browser to download that file and not showing it?
I'm working in a C#, Asp.net environment (with IIS7).
Thx
protected void DisplayDownloadDialog()
{
Response.Clear();
Response.AddHeader(
"content-disposition", string.Format("attachment; filename={0}", "filename.xml"));
Response.ContentType = "application/octet-stream";
Response.WriteFile("FilePath");
Response.End();
}
This will force to download the file and not display in the browser.
This will work for any file types
without requiring to specify any
special MIME type.
This is explained in this article: http://www.xefteri.com/articles/show.cfm?id=8
The key is in this line:
Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name)
Add a content-disposition: attachment header.

Response.WriteFile PDF files - corrupted files

I am having problem with writing PDF files to browser. Other mime types work fine.
PDF files become corrupted.
FileInfo file = new FileInfo(Path.Combine(_module.FileDir, _file.FilePath));
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = _file.ContentType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + Regex.Replace(_file.FilePath, "\\s", "-"));
Response.AppendHeader("Content-Length", file.Length.ToString());
try
{
Response.WriteFile(file.FullName);
Response.Flush();
Response.Close();
}
catch
{
Response.ClearContent();
}
My problem was with HTTP Module. I was applying White space filter
HttpApplication app = sender as HttpApplication;
if (app != null && app.Request.RawUrl.Contains(".aspx"))
{
app.Response.Filter = new WhitespaceFilter(app.Response.Filter);
}
IIS HTTP Compression and Streaming PDF's: Don't work well.
http://blog.1530technologies.com/2006/11/iis_http_compre.html
You need these three statements:
Response.Flush();
Response.Close();
Response.End();
The last one is the most important.
For this situation, a Response.Redirect should work just as well:
FileInfo file = new FileInfo(Path.Combine(_module.FileDir, _file.FilePath));
Response.Redirect(file.FullName);
Are you sure you're getting the right MIME type?
Are you attempting to force the user to download, or just stream out the PDF data?
Are you performing a Response.End() call anywhere to ensure that no extra data (outside of the headers and the PDF binary) is sent?
I'm thinking it's #3 that may be your issue here. Microsoft's Knowledge Base provides this code to do, essentially, what you seem to be doing.
//Set the appropriate ContentType.
Response.ContentType = "Application/pdf";
//Get the physical path to the file.
string FilePath = MapPath("acrobat.pdf");
//Write the file directly to the HTTP content output stream.
Response.WriteFile(FilePath);
Response.End();

Categories