IE11 writes HTML in Response.BinaryWrite instead of byte() content - asp.net

I have an ASP.NET (Framework 2.0) website which generates a CSV file and propmpts the user to Save or Open this file (IE native pop-up window). Recently some users upgraded their IE to version 11 and they get the file with HTML as content and not the actual CSV-style rows.
This is working in IE9 and below.
Code for Response.BinaryWrite:
Response.Buffer = False
Response.ClearContent()
Response.ClearHeaders()
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", "attachment;filename=FileExport.csv")
Response.BinaryWrite(Session("nExport"))
Session("nExport") = Nothing
Response.Flush()
Response.Close()
Response.End()
' Session("nExport") contains Byte()
Expected file content:
NR;FirstName;LastName
1;Bilbo;Baggins
File content if I select Save or Open:
"<!DOCTYPE html PUBLIC ""-//W3C//DTD XHTML 1.0 Transitional//EN"" ""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"">"
"<html xmlns=""http://www.w3.org/1999/xhtml"" >"
<head><title>
" Export"
</title></head>
<body>
" <form name=""form1"" method=""post"" action=""nExport.aspx?ID=RGVwbjsu3GFyamkyMDEz"" id=""form1"">"
<div>
"<input type=""hidden"" name=""__VIEWSTATE"" id=""__VIEWSTATE"" value=""/wEPDwUJNzgzNDMwNTMzZGSmoL1exQ/68hIbp0DWxDDjlt6wAA=="" />"
</div>
<div>
</div>
</form>
</body>
</html>
Edit: additional information from the user is that another (similar) CSV file download is working correctly. I will have to investigate some more, code for both downloads is the same.
Edit 2:
It seems to be working on UAT server, the solution was removing Response.End and Response.Close and use HttpApplication.CompleteRequest, as per this question ie-10-file-download-issues. Will have to investigate more and try on production servers.
Dim httpApp As New HttpApplication
httpApp.CompleteRequest()
'Response.Close()
'Response.End()

I can confirm a working solution on the production server also. As the comment from stun in this answer suggests I left Response.Close and Response.End after CompleteRequest.
This is the new Response method:
Response.Buffer = False
Response.ClearContent()
Response.ClearHeaders()
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", "attachment;filename=FileExport.csv")
Response.BinaryWrite(Session("nExport"))
Session("nExport") = Nothing
Response.Flush()
HttpContext.Current.ApplicationInstance.CompleteRequest()
Response.Close()
Response.End()
Edit: just a fix, using HttpContext.Current not making a new HttpApplication.

Related

Response.Write() vs Response.Outputstream()

I'm getting some strange behavoir with my xml-ouput.
I'm filling my xml using a Stringwriter and a xmltextwriter.
Using textw As New IO.StringWriter
Using xmlw As New System.Xml.XmlTextWriter(textw)
....
End Using
However when outputting the data. i'm getting two different results for the same ('in my eyes') methodoligy. In both situations tw will contain my xml
Non working version: (in IE)
Response.Clear()
Response.Write(textw.ToString)
Response.ContentEncoding = System.Text.Encoding.UTF8
Response.ContentType = "text/xml"
Response.End()
Errormessage is telling there is an error in the contents of my xml.
working version: (in IE)
Response.Clear()
Dim xmlDoc As New XmlDocument
xmlDoc.LoadXml(textw.ToString)
xmlDoc.Save(Response.OutputStream)
Response.ContentEncoding = System.Text.Encoding.UTF8
Response.ContentType = "text/xml"
Response.End()
Question: What is the difference between Response.write and Response.Outputstream?
Note: Both method appear to be working in firefox & chrome. The xml is valid as its already in use at the moment (using the working version).

Clearing a Response in Postback to download text file from Button Click

Now... I could do this is a separate page, but i don't want to!
I am trying to create a service which fetches a load of JS files required for a project, compresses them and downloads a single file, but what it does isn't really the issue, the downloading bit is not behaving as expected.
From many examples on here, including:
In ASP.NET, how to get the browser to download string content into a file? (C#)
I have the (simplified) code:
Sub Download() Handles button.click
var AllTheScript as string ="blah blah blah"
Response.Buffer = True
Response.Clear()
Response.ClearContent()
Response.Write(AllTheScript)
Response.ContentType = "application/text"
Response.AddHeader("content-disposition", "attachment; filename=myJavascript.js")
Response.Flush()
End Sub
Obviously, I also have an <asp:button id="button" runat="server"/> element in my page.
When I click this button, it does all the fetch work (not illustrated above) creates the text file and downloads it... excellent...
Except, at the bottom of the JS file it downloads myJavascript.js it has all the markup from the page in which the button was.
I was under the impression that Response.ClearContent() should remove all this?
What am I doing wrong? Or does this have to be a separate page?
In case anyone else comes across this issue again, I solved the problem, very simple!
All it needed was
Response.End()
At the end!
So the full function becomes:
Sub Download() Handles button.click
var AllTheScript as string ="blah blah blah"
Response.Buffer = True
Response.Clear()
Response.ClearContent()
Response.Write(AllTheScript)
Response.ContentType = "application/text"
Response.AddHeader("content-disposition", "attachment; filename=myJavascript.js")
Response.Flush()
Response.End() '///<<< Final Line Essential!
End Sub
Try this
var context = HttpContext.Current;
context.Response.Clear();
context.Response.ClearHeaders();
context.Response.ClearContent();
////
context.Response.AddHeader("content-disposition", "attachment; filename=myJavascript.js");
content.Response.Write(AllTheScript);

ASP.NET Downloadable Image Files?

I don't have apache support on this website, but I need to be able to allow images to be downloadable in a certain directory only. How can I do this? This site only has ASP.NET support, and it's killing me! Noticed this link: How to download files in mvc3? but not sure where to put that code at, or even if that code there would help me any.
Any help would be greatly appreciated! A Starting point or something...
Is there a way I can just do this in HTML? Like, for example, set the download link to point to an html file, where the HTML file grabs the image file and makes it downloadable, in and of itself?
So far I have the following ASP code in a file called: default.asp
Which begins the download just fine, but it downloads an empty file (download.jpg). How can I point the following code to an actual image file to download?
<%# Language=VBScript %>
<% Option Explicit
Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition", "attachment; filename=" + "download.jpg"
%>
I have a file named, "download.jpg" even within the same directory, but it never downloads the actual image. It downloads a 90 byte empty image file instead.
I even tried this with no luck:
<%# Language=VBScript %>
<% Option Explicit
Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition","attachment; filename=07awardee.png"
Response.TransmitFile Server.MapPath("~/images/07awardee.png")
Response.End
%>
And yes, I have the 07awardee.png file in images/07awardee.png on the server root and even in the folder root where default.asp is located. Arggg! What gives here? The file is a bit bigger now at 392 bytes, but it still isn't readable as an image file... I've been searching the internet and this is supposed to work, but doesn't! What could be the problem here?
Your .aspx page with a Request.End throws a ThreadAbortException, and that's bad for server performance (too many of these can even crash a server). So you'll want to avoid that. http://weblogs.asp.net/hajan/archive/2010/09/26/why-not-to-use-httpresponse-close-and-httpresponse-end.aspx
The way I handle this problem is with a HttpHandler (.ashx) and use that to serve downloadable image files. I used some of your code because my implementation was in C# and has much more code (includes image scaling options etc):
//<%# WebHandler Language="VB" Class="DownloadImage" %> // uncomment this line!
Public Class DownloadImage : Implements IHttpHandler
Protected EnabledTypes() As String = New String() {".jpg", ".gif", ".png"}
Public Sub ProcessRequest(ByVal context As HttpContext) _
Implements IHttpHandler.ProcessRequest
Dim request = context.Request
If Not String.IsNullOrEmpty(request.QueryString("file")) Then
Dim path As String = context.Server.MapPath(request.QueryString("file"))
Dim file As System.IO.FileInfo = New System.IO.FileInfo(path)
If file.Exists And EnabledTypes.Contains(file.Extension.ToLower()) Then
context.Response.Clear()
context.Response.AddHeader("Content-Disposition", _
"attachment; filename=" & file.Name)
context.Response.AddHeader("Content-Length", file.Length.ToString())
context.Response.ContentType = "application/octet-stream"
context.Response.WriteFile(file.FullName)
Else
context.Response.ContentType = "plain/text"
context.Response.Write("This file does not exist.")
End If
Else
context.Response.Write("Please provide a file to download.")
End If
End Sub
Public ReadOnly Property IsReusable() As Boolean _
Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
End Class
Make sure you implement a check for image files, otherwise you have a potential security problem. (Users could download web.config where database passwords are stored)
The link would become:
Download image
You should clear the header and provide the correct header and content type
Response.Clear()
Response.AppendHeader("Content-Disposition", "attachment; filename=somefilename")
Response.ContentType = "image/jpeg"
Response.TransmitFile(Server.MapPath("/xyz.jpg"));
Response.End();
OMG, I rock. Here's the way this is done. Create a file called, download.aspx, and input the following code into it:
<%# Page language="vb" runat="server" explicit="true" strict="true" %>
<script language="vb" runat="server">
Sub Page_Load(Sender As Object, E As EventArgs)
Dim strRequest As String = Request.QueryString("file")
If strRequest <> "" AND strRequest.EndsWith(".jpg") OR strRequest.EndsWith(".jpeg") OR strRequest.EndsWith(".png") OR strRequest.EndsWith(".gif") OR strRequest.EndsWith(".pdf") OR strRequest.EndsWith(".doc") OR strRequest.EndsWith(".docx") OR strRequest.EndsWith(".bmp") Then
Dim path As String = Server.MapPath(strRequest)
Dim file As System.IO.FileInfo = New System.IO.FileInfo(path)
If file.Exists Then
Response.Clear()
Response.AddHeader("Content-Disposition", "attachment; filename=" & file.Name)
Response.AddHeader("Content-Length", file.Length.ToString())
Response.ContentType = "application/octet-stream"
Response.WriteFile(file.FullName)
Response.End
Else
Response.Write("This file does not exist.")
End If
Else
Response.Write("You do not have permission to download this file type!")
End If
End Sub
</script>
Now, when you want to get a file to download (ANY FILE), just link it like so:
Download the logo image
And that's all she wrote!

When downloading a file from ASP .Net, the text file gets appended with HTML content

I have made a page that allows users to upload files to the server using a FileUpload Control and handling its event with this code
Sub SaveAttachment()
Dim root As String = "C:\temp\"
Dim filename As String = FileUpload1.FileName
Dim SaveName As String = root & filename
FileUpload1.SaveAs(SaveName)
End Sub
That worked fine, I was able to see files getting uploaded, and the content of the files is intact (exactly a duplicate copy of the file that the user's upload).
Now for downloading the files back to the user (at a later time) I have written another page that reads the file name from a Request.Parameter ("file") and fetches that file to be downloaded to the user. I have written the Download.aspx page to handle downloading in the ASP part (no code behind was used):
<%# Import Namespace="System.IO"%>
<script language="VB" runat="server">
Sub Page_Load(sender As Object, e As EventArgs)
Dim root As String = "C:\temp\"
Dim filepath As String = Request.Params("file")
If Not filepath Is Nothing Then
filepath = root & filepath
If File.Exists(filepath) And filepath.StartsWith(root) Then
Dim filename As String = Path.GetFileName(filepath)
Response.Clear()
Response.ContentType = "application/octet-stream"
Response.AddHeader("Content-Disposition", _
"attachment; filename=""" & filename & """")
Response.Flush()
Response.WriteFile(filepath)
End If
End If
End Sub
</script>
<form id="form1" runat="server">
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
</form>
I tried uploading images files and then downloading them again, and it worked fine. However, only when I upload text files that I get the content of that file appended with some HTML content.
Here is a sample file that I have uploaded
Here is my sample text file
It consists of 3 lines only
And here is the file when I downloaded it back
Here is my sample text file
It consists of 3 lines only
<form name="form1" method="post" action="FileDownload.aspx?file=sample_file.txt" id="form1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE5NTU5ODQyNTBkZNCYbOVZJDRUAOnIppQYkwHUSlb0" />
</div>
<span id="Label1">Label</span>
</form>
I went to the file on the server and opened it to make sure that the additional HTML content was there, but as I said, the file was uploaded perfectly. Only when it is downloaded does it contain appended HTML stuff.
What is it that I am doing wrong? What can I do to make this additional HTML code go away?
Why does this problem only affect Text file, not images, EXE, XLS, DOC ,, etc?
Make sure to end your Response by calling Response.End() after Response.WriteFile(filepath) or else your form will be appended to the stream and sent to the client.
It will affect other files as well though most likely only be seen as garbage at the end of the file and ignored by their respective applications.
Response.redirect threw an exception. Shoaib's answer got me closer but it suppressed everything including the valid file content. What worked for me was reordering the statements as follows:
Response.ContentType = ContentType
Response.AppendHeader("Content-Disposition", "attachment; filename=" & originalFileName)
Response.WriteFile(filePath)
Response.Flush()
Response.SuppressContent = True
HttpContext.Current.ApplicationInstance.CompleteRequest()
Is is not safe to use Response.End(), It will always return a System.Threading.ThreadAbortException:.. if debugged and seen in the catch block...
Alternative..
Use the following instead...
Response.Flush();
Response.SuppressContent = true;
Response.WriteFile(filepath);
HttpContext.Current.ApplicationInstance.CompleteRequest();

File does not begin with '%PDF-'

I am exporting the HTML Content to PDF.
System.IO.StringWriter sWriter = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWriter = new HtmlTextWriter(sWriter);
Response.Buffer = true;
FormId.RenderControl(htmlWriter);
Response.ContentType = "application/pdf";
// Added appropriate headers
Response.AddHeader("Content-Disposition", "inline; filename=XXX.pdf");
Response.AddHeader("Content-Length", htmlWriter.ToString().Length.ToString());
Response.Output.Write(sWriter.ToString());
Response.Flush();
Response.Close();
FormId is my Div past of the content..
I am getting the error as "File does not begin with '%PDF-'"
I have included Response.clear(); The output is not coming
You're rendering out the html (div as you said) before the pdf in the output stream, so the two are combined. That's causing any app looking at the output to interpret it as a corrupted file. I'd try removing the first two lines:
Response.Buffer = true;
FormId.RenderControl(htmlWriter);
If that doesn't solve the issue, add a Response.Clear() call before everything.
This is all assuming sWriter contains the PDF at the beginning of this code block -- if not, a little more context might be helpful.
Some advice: if at all possible, move this out of the page to a .ashx or other IHttpHandler.
I was facing the same issue while writing some HTML content to PDF.
I finally found that invalid HTML content causes this issue.
For example, <ul> tag without closing tag </ul>.
Once I put in the proper closing tags, it works fine!
Do a Response.Clear() before starting to stream your output.

Resources