Flushing stream of ZIP - c#

I'm trying to Flush a Zip file that has just been created, and have an issue with it:
a) it doesn't actually Flush (I used the code before with the CSV files and all works well)
Here is the code:
outputMemStream.Position = 0;
System.Web.HttpResponse Resp = System.Web.HttpContext.Current.Response;
Resp.ClearContent();
Resp.ClearHeaders();
Resp.ContentType = "application/zip";
Resp.AddHeader("Content-Disposition", "attachment; filename=\"download.zip\"");
//byte[] buff = outputMemStream.ToArray();
//File.WriteAllBytes(path, buff);
outputMemStream.CopyTo(Resp.OutputStream);
outputMemStream.Close();
outputMemStream.Dispose();
Resp.Flush();
Resp.End();
The stream is created correctly because I am able to save it and can check it later that it looks alright.. just that thing that my browser doesn't allow me to download it is quite annoying.
Cheers for your help!

it's in the aspx page (in the code behind .cs), in one of the method
that happens after pressing button "Export All"
This is probably the issue. The page is rendered both your file and your controls (including your "Export All" button).
Try moving the logic for downloading to a different page or handler that does nothing but return the file.

Related

Cannot Send File in Response

I have a code set that runs on the server, which correctly generates a zip file and stores it on the server. I have that file location as a physical path.
Nothing I have attempted has allowed me to use the response to the client to download that file.
Attempt 1:
System.IO.FileInfo fi = new System.IO.FileInfo(zipFilePath);
//setup HTML Download of provided Zip.
//application/zip
Response.ClearContent();
Response.Clear();
Response.ClearHeaders();
Response.Buffer = true;
Response.ContentType = "application / zip";
Response.AddHeader("Content-Disposition",
"attachment; filename=\"" + System.IO.Path.GetFileName(zipFilePath) + "\";");
Response.AddHeader("Content-Length", fi.Length.ToString());
Response.TransmitFile(zipFilePath);
Response.Flush();
Response.End();
No result. Code executes without error but there is no download to the client.
Attempt 2:
//Almost the same as attempt 1, but with WriteFile instead
Response.WriteFile(zipFilePath);
No Result, same as Attempt 1.
Attempt 3:
//Note: Same Header Section as Attempts 1 and 2
System.IO.BinaryReader reader = new System.IO.BinaryReader(new System.IO.FileStream(zipFilePath, System.IO.FileMode.Open));
int CHUNK = 1024;
List<byte> FileArray = new List<byte>();
while (reader.BaseStream.Position < reader.BaseStream.Length)
FileArray.AddRange(reader.ReadBytes(CHUNK));
byte[] bArray = FileArray.ToArray();
reader.Close();
Response.OutputStream.Write(bArray, 0, bArray.Length);
Response.Flush();
Response.End();
No Result, Same as previous attempts
Attempt 4:
//Identical to Attempt 3, but using BinaryWrite
Response.BinaryWrite(bArray);
No Result, Same as previous Attempts.
The Question
Every one of these code blocks runs with no error, But The Save File dialog NEVER appears. I get nothing at all. I cannot figure out for the life of me what I might be missing.
The File Path has been verified as correct
The Code is running on the server, not on the client, I cannot use the 'WebClient.Download' method for this reason
If anyone has any suggestions, I'm all ears. I have no idea how to get this file to download to the client.
I tested your code (attempt 1) and got it working fine with a test file. If the file path would be wrong, you'd get an System.IO.FileNotFoundException so that's probably not the issue.
A couple of ways to address this:
Try inspecting the webpage in, for example, Chrome by right-clicking
and choose inspect. Then click on Network tab, and refresh the
page (where you're supposed to get the file). Check the response
headers for that request - what is it?
Try setting content-type to application/octet-stream
Use debugger in Visual Studio and step through.
This turned out to be an Ajax related error causing issues between UpdatePanels and POST Responses.
The issue was fixed on the page load of the page by adding the call
ScriptManager.GetCurrent(Page).RegisterPostBackControl(btnGenerate);

Pdf is not getting open some time after BinaryWrite

I created the functionality to edit the existing PDf content(adding some text and images) and after that i am opening this pdf file for print or download and i am using this code
Pdf is not getting open some time after BinaryWrite
byte[] outBuf = outStream1.GetBuffer();
HttpContext.Current.Response.Expires = 0;
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename="test.pdf");
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.ContentEncoding = new System.Text.UTF8Encoding();
HttpContext.Current.Response.BinaryWrite(outBuf);
outStream.Close();
HttpContext.Current.Response.End();
It is working fine on local machine or development server and some time on server.
On server after some times it is opening blank page. And after browser cache clear or temp file clear it works
I am not getting it where is the problem may be some client browser memory problem.
But if it is browser memory issue the it should also come on local too because I am using the same browser.
Please give me some idea or solution so that I can sort our this thing.
The GetBuffer method only returns exactly the content of the memory stream if it was created as a readonly stream from an array of bytes to begin with. Otherwise it returns the internal buffer, which may contain unused bytes at the end.
Use the ToArray method to get exactly the content of the memory stream, and nothing more:
byte[] outBuf = outStream1.ToArray();
Another thing that triggers some browsers some of the time to treat your stream as PDF, is to append some dummy argument to your URL so that it ends with ".pdf". I am not sure if this is really necessary in your case since your are setting the 'content-disposition' to 'attachment'. It won't hurt though.

Stream PDF to browser?

Could anyone please tell me how could I stream a pdf to a new tab browser? I just have the pdf stream on memory and I want when I click over the link to show the PDF in a new tab or window browser.
How could I do that?
Thank!!!
I have this link:
<a id="hrefPdf" runat="server" href="#" target="_blank"><asp:Literal ID="PdfName" runat="server"></asp:Literal></a>
In my code behind I have this on the onload event:
Stream pdf= getPdf
if (pdf != null)
{
SetLinkPDF(pdf);
}
private void SetLinkPDF(IFile pdf)
{
hrefPdf.href = "MyPDF to the Browser"
PdfName.Text = pdf.PdfName;
}
Someway I have to process the stream pdf (IFile contains Name, Stream,Metadata, etc of the PDF)
What can I do to proccess this and whe I click show the stream at a new browser?
I have another probelm, is not working the OnClientClick="aspnetForm.target='_blank';" timbck2 suggested me. I have to open the file (image or pdf ) in a new window, what could I do? Is not working this. Thank!
Timbbck2 my asp code is:
<asp:LinkButton runat="server" ID="LinkButtonFile" OnClick="LinkButtonFile_Click" OnClientClick="aspnetForm.target = '_blank';"></asp:LinkButton>
Thanks!!!
I've done this from a file on disk - sending the data from a memory stream shouldn't be that much different. You need to supply two pieces of metadata to the browser, in addition to the data itself. First you need to supply the MIME type of the data (in your case it would be application/pdf), then the size of the data in bytes (integer) in a Content-Length header, then send the data itself.
So in summary (taking into account the comments and what I think you're asking, your markup would look like this:
<asp:LinkButton ID="whatever" runat="server" OnClick="lnkButton_Click"
OnClientClick="aspnetForm.target='_blank';">your link text</aspnet:LinkButton>
These few lines of C# code in your code behind should do the trick (more or less):
protected void lnkButton_Click(object sender, EventArgs e)
{
Response.ClearContent();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "inline; filename=" + docName);
Response.AddHeader("Content-Length", docSize.ToString());
Response.BinaryWrite((byte[])docStream);
Response.End();
}
To display pdf directly in the browser you should set content type for the response to application/pdf
Your user should also have some kind of pdf reader installed for this to work.
Did you try Response.BinaryWrite?? You probably want to set some headers as well.
The top answer suggests converting (casting) a stream to a byte[] first, that will download the file to the server (from whatever stream it is coming from) and then send it to the client.
If you need to provide a Stream as a parameter for some external service (like me for Azure Storage) you can use the following method.
public ActionResult Coupons(string file)
{
Response.AddHeader("Content-Disposition", "inline; filename=" + file);
Response.ContentType = "application/pdf";
AzureStorage.DownloadFile(file, Response.OutputStream);//second parameters asks for a 'Stream', you can use whatever stream you want here, just put it in the Response.OutputStream
return new EmptyResult();
}
That will Stream the file to the client directly (as far as I know).

How to create file for download using Response class and then interact with the client?

I have a button and its OnClientClick event calls Generate().
function Generate() {
window.open('GenerateKey.aspx', '_newtab', 'titlebar = no', false);
PageMethods.SendKey(SendKeyCallback, SendKeyCallbackError);
}
The callbacks functions hide the loading gif and alert the status (success/failed)
GenerateKey.aspx creates a file and opens a download popup.
this is the page_load code:
string keyFileName = orgName + "-" + timeStamp + ".ckey";
fs = new FileStream(Server.MapPath("~/License/Generate/" + keyFileName), FileMode.Create, FileAccess.ReadWrite);
sw = new StreamWriter(fs);
sw.Write(generatedKey);
sw.Flush();
fs.Close();
Response.ContentType = "text/xml";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + keyFileName);
Response.TransmitFile(Server.MapPath("~/License/Generate/" + keyFileName));
Response.End();
The code works fine, but my problem is that the new tab is closed after the download pops up to the screen (I guess it happens because of the Response object), and it looks like a bug.
I get popup of a new blank tab for 1 second and then it closed.
Anyone has an idea how to make it look better?
I can't do it on the same page, because after the file generation I don't have a connection to the client any more (that's why I used window.open).
You're asking the browser to open a text file in another window. The browser is probably interpreting the data as not HTML, storing the file to disk, and closing the window afterwards--that's fairly standard for browsers. If that's not want you want, you need to send HTML data to the browser or configure your browser not to automatically save that type of data to disk.

Can I download an Excel file made from a memory stream off an ASP.NET page?

I have an ASP.NET page where a user provides an ID, and then we pull some data from the DB and put it into an Excel spreadsheet. I would like to create the Excel file in memory and then allow the user to download the file. I could create a file on the server, and then delete it afterwards, but it seems unnecessary. Depending on error handling I could potentially orphan a file with that approach, etc.
Is something like this possible? Or do I need to use a file stream?
On a side note, I'm using EPPlus as an API (quick plug for it).
You want to specify the content-type and content-dispisition headers like so - Response.ContentType = "application/vnd.ms-excel" works in IE and firefox but not in Safari, then stream your file. Once complete, call Response.End() to stop the application execution
Code Sample:
void StreamExcelFile(byte[] bytes)
{
Response.Clear();
Response.ContentType = "application/force-download";
Response.AddHeader("content-disposition", "attachment; filename=name_you_file.xls");
Response.BinaryWrite(bytes);
Response.End();
}
ExcelPackage pck = new ExcelPackage();
.....
.....
.....
byte[] bfr = pck.GetAsByteArray();
Response.ContentType = "application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AppendHeader("content-disposition", "attachment; filename=ExcelFileName.xlsx");
Response.OutputStream.Write(bfr, 0, bfr.Length);
Response.Flush();
Response.Close();
Yes, look into using an HTTP Handler to stream the file to the browser from memory.
http://msdn.microsoft.com/en-us/library/ms972953.aspx
What you're looking for is called a generic handler:
http://www.dotnetperls.com/ashx
In a nutshell, what you need to do is define the context type. Which in your case will be a xls or xlsx. Set the response, and direct the user to the handler.
They will be prompted to download the file.

Categories

Resources