ASP.NET stream content from memory and not from file - asp.net

The users have requested the option to "download" a csv file representation of GridView contents. Does anyone know how to do this without saving the file to the server but rather just streaming it to the user from memory?
Thanks

Implement an IHttpHandler.
I used something similar to the following in the ProcessResponse for outputing a CSV that had previously been constructed in a database table...
public void ProcessRequest(HttpContext context)
{
HttpResponse response = context.Response;
HttpRequest request = context.Request;
//Get data to output here...
//Turn off Caching and enforce a content type that will prompt to download/save.
response.AddHeader("Connection", "close");
response.AddHeader("Cache-Control", "private");
response.ContentType = "application/octect-stream";
//Give the browser a hint at the name of the file.
response.AddHeader("content-disposition", string.Format("attachment; filename={0}", _filename));
//Output the CSV here...
foreach(BatchDTO.BatchRecordsRow row in dtoBatch.BatchRecords)
response.Output.WriteLine(row.Data);
response.Flush();
response.Close();
}
There are a number of libraries that make generating a CSV easier, you should just be able to pass it the Response.OutputStream to have it write to there rather than to a file stream.

Use context.Response.OutputStream.
Here's an example.

I created a StringBuilder and dump the contents to the Response object using the following code ("csv" is the StringBuilder variable).
Response.ContentType = #"application/x-msdownload";
Response.AppendHeader("content-disposition", "attachment; filename=" + FILE_NAME);
Response.Write(csv.ToString());
Response.Flush();
Response.End();

I have used the RKLib export library a few times to great effect, this uses a memory stream and can be given any datatable which it will export as a csv download:
http://www.codeproject.com/KB/aspnet/ExportClassLibrary.aspx

Related

Getting a corrupted XLSX file when writing it to Response.OutputStream

In ASP.Net, I'm using NPOI to write save to an Excel doc and I've just moved to version 2+. It worked fine writing to xls but switching to xlsx is a little more challenging. My new and improved code is adding lots of NUL characters to the output file.
The result is that Excel complains that there is "a problem with some content" and do I want them to try to recover?
Here is a pic of the xlsx file that was created from my Hex editor:
BadXlsxHexImage Those 00s go on for several pages. I literally deleted those in the editor until the file opened without an error.
Why does this code add so many NULs to this file??
using (var exportData = new MemoryStream())
{
workbook.Write(exportData);
byte[] buf = exportData.GetBuffer();
string saveAsFileName = sFileName + ".xlsx";
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}; size={1}", saveAsFileName, buf.Length.ToString()));
Response.Clear();
Response.OutputStream.Write(buf, 0, buf.Length);
exportData.Close();
Response.BufferOutput = true;
Response.Flush();
Response.Close();
}
(I've already tried BinaryWrite in place of OutputStream.Write, Response.End in place of Response.Close, and setting Content-Length with the length of the buffer. Also, none of this was an issue writing to xls.)
The reason you are getting a bunch of null bytes is because you are using GetBuffer on the MemoryStream. This will return the entire allocated internal buffer array, which will include unused bytes that are beyond the end of the data if the buffer is not completely full. If you want to get just the data in the buffer (which you definitely do), then you should use ToArray instead.
That being said, why are you writing to a MemoryStream at all? You already have a stream to write to: the OutputStream. Just write the workbook directly to that.
Try it like this:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", saveAsFileName));
workbook.Write(Response.OutputStream);
Response.Flush();
Response.Close();

download code expalanation in asp.net

can anyone please explain this code
if (e.CommandName == "download")
{
string filename = e.CommandArgument.ToString();
string path = MapPath("~/Docfiles/" + filename);
byte[] bts = System.IO.File.ReadAllBytes(path);
Response.Clear();
Response.ClearHeaders();
Response.AddHeader("Content-Type", "Application/octet-stream");
Response.AddHeader("Content-Length", bts.Length.ToString());
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
Response.BinaryWrite(bts);
Response.Flush();
Response.End();
}
what is command argument, mappath, and also what is this
"Content-Type", "Application/octet-stream"
and also
Response.AddHeader("Content-Length", bts.Length.ToString());
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
Response.BinaryWrite(bts);
Response.Flush();
First, I advise you to use the MSDN documentation to search for more information about the objects and methods you wanna know more about. MSDN is a useful network and should be used.
Quoting the MSDN CommandArgument : "Gets or sets an optional parameter passed to the Command event along with the associated CommandName". It is used to get an parameter that was passed to the command event. In this case, it was the file name.
string filename = e.CommandArgument.ToString();
The MapPath is used to map a specified path to a physical path. Using this you get the real path of the file. For example: "C:\Docfiles\Yourfile.pdf"
string path = MapPath("~/Docfiles/" + filename);
The ReadAllBytes method, opens a file, reads the content and then closes the file. This return the content of this file as a byte array.
byte[] bts = System.IO.File.ReadAllBytes(path);
The Response object is used to send output to the user from the server.
Response.Clear();
Response.ClearHeaders();
Response.AddHeader is used to build the header of response that will be sent back to user. We use it to set infos about the data we are sending back to the client.
The "Content-Type" attribute is used to especify what kind of file you are returning to the user.
Response.AddHeader("Content-Type", "Application/octet-stream");
The "Content-Length" attribute is used to inform to the browser the size of the the file you are returning.
Response.AddHeader("Content-Length", bts.Length.ToString());
The "Content-Disposition" is used to inform the name of the file that will be returned. For example "file1.doc"
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
The "BinaryWrite()" write your file (who, at this moment, is in a byte array format) to the current HTTP output without any character conversion.
Response.BinaryWrite(bts);
The Flush method sends buffered output immediately.
Response.Flush();
And, finally, causes the server to stop processing the request and return the current result.
Response.End();
If the command is download, most likely from a grid button, then get the name of the file as the argument (these are properties on a button control), and send it to the browser. This prompts the user to download the file.

ASP.Net Transmit File

I am writing a webapplication in ASP.net.
I am trying to make a file dialog box appear for downloading something off the server.
I have the appropriate file data stored in a variable called file.
File has fields:
FileType - The MIMEType of the file
FilePath - The server-side file path
Here's the code so far:
Response.Clear();
Response.ContentType = file.FileType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + GetFileName(file));
Response.TransmitFile(file.FilePath) ;
Response.End();
GetFileName is a function that gets me the filename from an attachment object. I only store the path.
The above code is in a function called "Download_Clicked" that is an event that triggers on click. The event is mapped to a LinkButton.
The problem is that when I run the above code, nothing happens. The standard dialog box does not appear.
I have attempted the standard trouble-shooting such as making sure the file exists, and ensuring the path is correct. They are both dead on the mark.
My guess is that because my machine is also the server, it may not be processing properly somehow.
Thanks in advance.
Edit 1: Attempted putting control onto another page, works fine.
Edit 2: Resolved issue by removing control from AJAX Update Panel.
I've found another to do this without removing the update panel. Place the code below in your page load and you'll now be able to use that button to trigger a download.
ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(Button);
Use Response.WriteFile() instead.
Also, don't use Response.End()! This aborts the thread. Use Response.Flush(); Response.Close();
Try changing
Response.AppendHeader("Content-Disposition", "attachment; filename=" + GetFileName(file));
To
Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(GetFileName(file))));
If that doesn't work, you can always use Response.BinaryWrite or Resonse.Write to stream the file to the web browser
Here is how transmit the file using Response.Write or Response.BinaryWrite. Put these functions in a library somewhere then call them as needed
public void SendFileToBrowser(String FileName, String MIMEType, String FileData)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.ContentType = MIMEType;
Response.Buffer = true;
Response.Write(FileData);
Response.End();
}
public void SendFileToBrowser(String FileName, String MIMEType, Byte[] FileData)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.ContentType = MIMEType;
Response.Buffer = true;
Response.BinaryWrite(FileData);
Response.End();
}
Then somewhere you call these functions like so
SendFileToBrowser("FileName.txt", "text/plain", "Don't try this from an Update Panel. MSAjax does not like it when you mess with the response stream.");
See edit on initial post.
Removed Ajax Update Panel to resolve the error. The panel was stopping the post back to the server.
For more info, see Cris Valenzuela's comment.

How to write the context of a FileStream to my ASP.net HTTP Response?

Suppose that I want my ASP.net web server to open a file and then send it to the browser.
First, I write this:
FileInfo file = new System.IO.FileInfo(#"\\myshare\myfile.zip");
FileStream fileStream = file.Open(FileMode.Open, FileAccess.Read, FileShare.Read);
What comes next?
I would think something along the lines of Response.Write(..., but I'm having trouble figuring it out.
straight from MSDN:
HttpResponse.BinaryWrite Method
FileStream MyFileStream;
long FileSize;
MyFileStream = new FileStream("sometext.txt", FileMode.Open);
FileSize = MyFileStream.Length;
byte[] Buffer = new byte[(int)FileSize];
MyFileStream.Read(Buffer, 0, (int)FileSize);
MyFileStream.Close();
Response.Write("<b>File Contents: </b>");
Response.BinaryWrite(Buffer);
Edit: of course there are also many other methods, like streaming which allows you to never allocate the byte[] buffer all at once on the web server. This was just a starting point...
A good way to send files is using the content-disposition header before you send the actual raw data
for instance:
Response.ContentType = "application/jpeg";
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
Response.WriteFile(path);
Response.End();
where fileName is just the filename (with extension)
and path is the full path to the file

What am I doing wrong with HttpResponse content and headers when downloading a file?

I want to download a PDF file from a SQL Server database which is stored in a binary column. There is a LinkButton on an aspx page. The event handler of this button looks like this:
protected void LinkButtonDownload(object sender, EventArgs e)
{
...
byte[] aByteArray;
// Read binary data from database into this ByteArray
// aByteArray has the size: 55406 byte
Response.ClearHeaders();
Response.ClearContent();
Response.BufferOutput = true;
Response.AddHeader("Content-Disposition", "attachment; filename=" + "12345.pdf");
Response.ContentType = "application/pdf";
using (BinaryWriter aWriter = new BinaryWriter(Response.OutputStream))
{
aWriter.Write(aByteArray, 0, aByteArray.Length);
}
}
A "File Open/Save dialog" is offered in my browser. When I store this file "12345.pdf" to disk, the file has a size of 71523 Byte. The additional 16kB at the end of the PDF file are the HTML code of my page (as I can see when I view the file in an editor). I am confused because I was believing that ClearContent and ClearHeaders would ensure that the page content is not sent together with the file content.
What am I doing wrong here?
Thanks for help!
I think you want a Response.End at the end of this method.
In a quick glance, you're missing Response.End();

Resources