Returning a downloadable file using a stream in asp.net web forms - asp.net

In asp.net MVC I can do something like the following which will open a stream:
Stream strm1 = GenerateReport(Id);
return File(strm1,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Report_" + reportId.ToString() + ".xlsx");
Notice how I am passing strm1 which is a stream. I can then name it Report_+ ...xlsx like the example above shows.
Is there a similar way to do this with asp.net web forms using c#.

You can use TransmitFile or WriteFile if the file is in your website folder.
string fileName = string.Format("Report_{0}.xlsx", reportId);
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition",
string.Format("attachment; filename={0}", fileName));
Response.TransmitFile(fileName);
Response.End();
Stream
If your data is already in Memory, you want this method which writes the response in chunks.
Stream stm1 = GenerateReport(Id);
Int16 bufferSize = 1024;
byte[] buffer = new byte[bufferSize + 1];
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition",
string.Format("attachment; filename=\"Report_{0}.xlsx\";", reportId));
Response.BufferOutput = false;
int count = stm1.Read(buffer, 0, bufferSize);
while (count > 0)
{
Response.OutputStream.Write(buffer, 0, count);
count = stm1.Read(buffer, 0, bufferSize);
}

I use this extension to send a stream as a downloadable file:
public static class ToDownloadExtention
{
public static void ToDownload(this Stream stream, string fileName, HttpResponse response)
{
response.Clear();
response.ContentType = "application/octet-stream";
response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", fileName));
stream.CopyTo(response.OutputStream);
response.End();
}
}
And the usage is:
var stream = new MemoryStream();
stream.ToDownload("someFileName.ext",Response);

Or if you have a stream ready to be written, simply copy it to response stream:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment; filename={your file name}");
Response.OutputStream.Write(stream, 0, stream.length);
Response.End();
Added same code just for visibility

Related

Getting Out of Memory Exception when downloading large files

I developed ASP.NET web application. I am trying to download the document from file server. FileSize maybe more than 1GB.
Here the thing is, very first time file got downloaded. when i click the same link, i am getting "Out of memory Exception" throws error.
If it is small size file, i don't get any issues to download the filles...
How do we handle this error if i download the document more than 1GB...?
below is the code to download the file in ASP.NET (Code behind file)
Dim binFile As Byte() = File.ReadAllBytes(filename)
Response.ContentType = "application/octet-stream"
Response.AppendHeader("Content-Disposition", "attachment; filename=" + filename)
Response.BinaryWrite(binFile)
Response.End()
Response.BinaryWrite() buffers whole file into memory, you can Use HttpResponse.TransmitFile() which don't buffer the file in memory.
Better solution is to send file as chunks, stream and ...
Here is a sample for download file without buffer
using (FileStream fileStream = File.OpenRead("full path to file"))
{
int bufferSize = 10 * 1024;
byte[] buffer = new byte[bufferSize];
long dataToRead = fileStream.Length;
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", "attachment; filename=FILE_NAME_THAT_USER_MUST_SEE");
Response.AddHeader("Content-Length", fileStream.Length.ToString());
while (dataToRead > 0)
if (Response.IsClientConnected)
{
int readLength = fileStream.Read(buffer, 0, bufferSize);
Response.OutputStream.Write(buffer, 0, readLength);
Response.Flush();
buffer = new byte[bufferSize - 1 + 1];
dataToRead -= readLength;
}
else
break;
}
Response.Close();

Response.Flush() method is not working

Response.Flush method is not working. I am getting the data at pdfContent but it is not opening the PDF documnet. Below is the code. Please help.
public ActionResult PdfClick(int requestid)
{
BusinessRequestController bsnrqstcntrlr = new BusinessRequestController();
try
{
int DocId = (new BusinessRequestBR()).GetBaseLineDocumentsForSearch(requestid);
byte[] PdfContent = (new BusinessRequestHelper()).GetBaseLineDonload(DocId);
Response.Buffer = true;
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=" + "BaseLine_Doc" + "_" + DocId + ".pdf");
Response.BinaryWrite(PdfContent);
Response.Flush();
return Content("");
}
catch (Exception ex)
{
throw this.log.CreatePropagatedException(ex);
}
Instead of using
return Content("")
use this:
return File(
PdfContent,
"application/pdf",
string.Format("BaseLine_Doc{0}.pdf", DocId)
)
There is no need to manipulate the response. Just return the correct result type.
Pulling out code from my running project
Response.Clear();
Response.AddHeader("Content-Disposition","attachment; filename=\"" + file[0].Name + "\"");
Response.AddHeader("Content-Length", fileSize.ToString(_culture));
Response.ContentType = Path.GetExtension(file[0].Name).GetMimeType();
Response.BufferOutput = false;
Response.AddHeader("Accept-Ranges", "bytes"); //tell the client that we accept byte-range requests
while (totalBytesRead < fileSize)
{
if (!Response.IsClientConnected)
{
System.Diagnostics.Debug.WriteLine("--> Client disconnected");
break;
}
int bytesRead = fs.Read(buffer, 0, buffer.Length);
Response.OutputStream.Write(buffer, 0, bytesRead);
Response.Flush();
totalBytesRead += bytesRead;
}
Response.End();
This code works for me every time, please manipulate according to your need.
Note: Variables are defined above the code.

ASP.net download file Using HttpContext.Current.Response.TransmitFile in ASP.NET

public void Downloadfile(string sFileName, string sFilePath)
{
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.ContentType = "APPLICATION/OCTET-STREAM";
String Header = "Attachment; Filename=" + sFileName;
HttpContext.Current.Response.AppendHeader("Content-Disposition", Header);
HttpContext.Current.Response.AppendHeader("Cache-Control", "no-cache");
System.IO.FileInfo Dfile = new System.IO.FileInfo(HttpContext.Current.Server.MapPath(sFilePath));
HttpContext.Current.Response.TransmitFile(Dfile.FullName);
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
I have a download button, the click will return the call and download the corresponding file download, but sometimes file returns is detailt.aspx file. I do not understand what is happening.
I need help. Thanks a lot
This has worked for me with out issue for a while now.
public void Downloadfile(string sFileName, string sFilePath)
{
var file = new System.IO.FileInfo(sFilePath);
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + sFileName);
Response.AddHeader("Content-Length", file.Length.ToString(CultureInfo.InvariantCulture));
Response.ContentType = "application/octet-stream";
Response.WriteFile(file.FullName);
Response.End();
}

Downloading file on client side using absolute path .NET

string FilePath = HttpUtility.UrlDecode(Request.QueryString.ToString());
string[] s = FilePath.Split(new char[] { ',' });
string path = s[0];
string FileName = s[1];
String str = HttpContext.Current.Request.Url.AbsolutePath;
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
// response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName+ ";");
response.TransmitFile(path+FileName);
response.Flush();
response.End();
Above is the code in which i get location of audio file from another page . the audio file is located on a remote machine which is accesible using url e.g. http:\servername\audiofiles\filename.wav . response.Transmit and .WriteFile requires virtual path whereas response.Write() does not download file . How can i give the absolute url instead of virtual path to download file
Found the answer my self from another place :
string FilePath = HttpUtility.UrlDecode(Request.QueryString.ToString());
string[] s = FilePath.Split(new char[] { ',' });
string path = s[0];
string FileName = s[1];
int bytesToRead = 10000;
byte[] buffer = new Byte[bytesToRead];
try
{
HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create(path+FileName);
HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();
if (fileReq.ContentLength > 0)
fileResp.ContentLength = fileReq.ContentLength;
stream = fileResp.GetResponseStream();
var resp = HttpContext.Current.Response;
resp.ContentType = "application/octet-stream";
resp.AddHeader("Content-Disposition", "attachment; filename=\"" + FileName + "\"");
resp.AddHeader("Content-Length", fileResp.ContentLength.ToString());
int length;
do
{
if (resp.IsClientConnected)
{
// Read data into the buffer.
length = stream.Read(buffer, 0, bytesToRead);
// and write it out to the response's output stream
resp.OutputStream.Write(buffer, 0, length);
resp.Flush();
//Clear the buffer
buffer = new Byte[bytesToRead];
}
else
{
// cancel the download if client has disconnected
length = -1;
}
} while (length > 0); //Repeat until no data is read
}
finally
{
if (stream != null)
{
//Close the input stream
stream.Close();
}
}
}

C# Asp Net Problem with download in Chrome 12

I have a problem in my project.
I have some code for downloading content as: .doc, .zip etc
It was working fine until chrome update for version 12, after that the browser shows an error message: "Download Interrupted".
I already tested in other browsers (Chrome 11, FF and IE8) and everything works fine.
An code sample is:
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.AppendHeader("Content-Type", "application/msword");
HttpContext.Current.Response.AppendHeader("Content-disposition", "attachment; filename=" + filename + ".doc");
HttpContext.Current.Response.AppendHeader("Content-Transfer-Encoding", "binary");
HttpContext.Current.Response.Write(strBody);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.Close();
Someone know what can be happening or how I can fix that?
Ps. Sorry my english, I'm brazilian :)
According to an answer in this forum adding Response.End() solved the issue.
In your case, it would be
HttpContext.Current.Response.Write(strBody);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
HttpContext.Current.Response.Close();
I am getting my binary data from sql server database with this code and it is working in all browser;
DataTable table = SiteFileAccess.GetDataByFileID(fileId);
byte[] b = (byte[])table.Rows[0]["FileData"];
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + table.Rows[0]["FileName"].ToString());
Response.AddHeader("Content-Length", b.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.BinaryWrite(b);
Response.Flush();
Response.End();
See the above code and fix it according to your need. Let me know If you need further information
string applicationName = Session["ApplicationName_UtilityDetail"].ToString();
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(Session["DownloadLink_UtilityDetail"].ToString());
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
int bufferSize = 1;
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.AppendHeader("Content-Disposition:", "attachment; filename=" + applicationName + ".zip");
Response.AppendHeader("Content-Length", objResponse.ContentLength.ToString());
Response.ContentType = "application/download";
byte[] byteBuffer = new byte[bufferSize + 1];
MemoryStream memStrm = new MemoryStream(byteBuffer, true);
Stream strm = objRequest.GetResponse().GetResponseStream();
byte[] bytes = new byte[bufferSize + 1];
while (strm.Read(byteBuffer, 0, byteBuffer.Length) > 0)
{
Response.BinaryWrite(memStrm.ToArray());
Response.Flush();
}
Response.Close();
Response.End();
memStrm.Close();
memStrm.Dispose();
strm.Dispose();
Try this:
Response.Buffer = true;
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment; filename=yourExcelFileName.xlsx;");
Response.BinaryWrite(yourByteArray);
Response.End();

Resources