I have an aspx (say 1.aspx) page from where first I am downloading a pdf file and then I want to redirect to some Thanks.aspx page. The code is this:
protected void btnSubmit_Click(object sender, EventArgs e)
{
string pathId = string.Empty;
if (Page.IsValid)
{
try
{
pathId = hidId.Value;
DownloadPDF(pathId);
Response.Redirect("Thanks.aspx");
}
catch (Exception ex)
{
throw ex;
}
}
}
protected void DownloadPDF(string pathId)
{
if (!(string.IsNullOrEmpty(pathId)))
{
try
{
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + pathId + ".pdf");
string path = ConfigurationManager.AppSettings["Pdf_Path"].ToString() + "\\" + pathId.Trim() + ".pdf";
Response.TransmitFile(path);
}
catch (Exception ex)
{
throw ex;
}
finally
{
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
}
The problem is that, the file save dialog is coming properly and I am able to download the file also, but it is not getting redirected to the Thanks.aspx page.
How to resolve this?
If the file is just downloaded, no preprocessing is done, you could try the following:
Response.AddHeader("Refresh", "12;URL=nextpage.aspx");
Where the number is the seconds before refresh is done :)
I've found it easier to put the PDF download page in an iframe. That way you can activate the PDF download on the client side by just pointing the iframe source to the PDF download page. After that you can either move to a new page, or just show the thank you text right that on the page that has the iframe in it.
In HTTP, a request can only have a single response. Since the first response is the PDF file, the seconds response (i.e. the redirect) cannot be implemented.
You can try to redesign the two pages by redirecting to thanks.aspx and have thanks.aspx start the download automatically.
A Response.Redirect actually sends a response to the browser that basically says this resource has moved to some other URL. However, you're trying to send a file down in a response too, so those two things are probably clashing with each other. Try sending back a little JavaScript that sends them to the page you want to send them too instead of using a Response.Redirect.
ScriptManager.RegisterStartupScript(Me, Me.GetType(), "redirectScript", "window.location.href='whateverurlhere.aspx';", True)
See the article mentioned in this accepted answer: https://stackoverflow.com/a/11018277/1037864
(direct link: http://gruffcode.com/2010/10/28/detecting-the-file-download-dialog-in-the-browser/)
The idea is to set a cookie and send it together with the file. Meanwhile you let the waiting page block the UI while it is waiting for the cookie to arrive.
I tried many things (like the ideas here) but nothing worked for my particular situation. In the end for me I used an approach where my C# sets a cookie that the JavaScript looks for and the form buttons/etc are disabled accordingly until the cookie is detected.
My code is here in case anyone thinks this solution might work for you:
https://gist.github.com/cemerson/9811a384d7f41bc683b2bd9ed4bf5b17
Related
In my page i am trying to download file. THe file is downloaded successfully but i get System.Threading.ThreadAbortException. So i handled that in my try Catch Block and set the error lable to blank but it doesnt get updated in page.
catch (System.Threading.ThreadAbortException)
{
lblErrorMsg.Text = "dfdf";
}
catch (Exception ex)
{
lblErrorMsg.Text = "Error while processing you request :<br> Erorr Description : " + ex.Message;
}
This is my Write file function
public static void WriteFile(string nameOfFile, string fileContent, HttpResponse writer)
{
writer.ClearHeaders();
writer.ClearContent();
writer.ContentType = "text/xml";
writer.AppendHeader("Content-Disposition", "attachment; filename=" + nameOfFile);
writer.Write(fileContent);
writer.Flush();
writer.End();
}
Can someone tell why label is not set to blank even though it comes under the Catch Block of system.thread.threadabortexceptiopn when i debug code ?
ThreadAbortException happens because you close the Response prematurely, by calling End() method of Response object.
This also explains why it's too late to write on the page content. It's not a very annoying error but it would be better to handle it cleanly.
Just check these answers Why Response.Redirect causes System.Threading.ThreadAbortException? or How to Avoid Response.End() "Thread was being aborted" Exception during the Excel file download and other answers related to Response and ThreadAbortException to understand it and handle properly by writing a better code for file download, according your usage.
Also please note that doesn't make a great sense to have both a completely rewritten Response stream for a page and some content on it, like a Label.
I am writing large CSV files to the Response with Response.BufferOutput set to false. This is because the file has the potential to take a long time to download so the user can see some progress. I generate a line for the CSV from a object and write to the response using Response.Write().
This works well however if there is an unexpected error after the Response has started writing then the client will receive a file with only part of the data and could be missing lots of lines but they might not realise it.
Is there a way to somehow cancel the file download without buffering all the content? Could there be some way to indicate that the response is invalid so the browser disregards the file?
Code below shows the main idea of my code
public void StreamCsvFile(string fileName,List<myObject> myObjectList)
{
Response.Clear();
Response.ContentType = "text/csv";
Response.AddHeader("content-disposition", "filename=" + fileName);
Response.BufferOutput = false;
string headerLine = GetHeaderLine();
Response.Write(headerLine)
try
{
foreach(var myObject in myObjectList)
{
string line = myObject.ToCsvString();
Response.Write("\n" + line);
}
}
finally
{
Response.End();
}
}
Write to a temporary file first.
Set the content-length on the response.
Use Response.TransmitFile to send this temp file.
Browsers will reject download if content length doesn't match.
I'm trying to create a file handler for users to download files when their filenames are clicked on a web page. I've implemented this a few times without issues, but I'm currently getting an error which I can't get my head around.
Code:
protected void btnViewFile_Click(object sender, EventArgs e)
{
var btnViewFile = sender as LinkButton;
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + btnViewFile.CommandArgument.ToString());
Response.WriteFile(Server.MapPath(btnViewFile.CommandArgument));
Response.End();
}
If I look at the browser console, I can see:
Uncaught Sys.WebForms.PageRequestManagerParserErrorException: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed.
No exceptions appear to be thrown in the code, the requested file is converted into the correct full path; and I've tried quite a few different things - clearing headers manually, flushing before ending, giving a more explicit content-type header, using AddHeader instead of AppendHeader, using TransmitFile rather than WriteFile, and quite a bit more.
Any ideas?
In case anyone else comes across this situation, the problem was that I was registering it as a postback control in ScriptManager, not an async postback control.
D'oh!
I have an ASP.NET (webforms) page that renders MS-Excel back to the response stream on click of a button. Everything works perfectly in testing but on live deployment, I get this dialogue box after the browser appears to be trying to download the file:
where ReportsShow.aspx is the name of the aspx page that generates and renders the excel.
The button that triggers the download fires a postback so I am confounded as to why the page would not be found when it renders correctly on load?
I am clueless and any help would be greatly appreciated
EDIT: As requested by Mayank, here's the code structure:
// Get instance of reporting service
IReportingService reportingServiceClient = Reports.GetWebService();
// Get a fresh copy of the report
BusinessReport theReport = reportingServiceClient.GetReport(AcctList.ToArray());
ExcelExport excelExport = new ExcelExport();
const string templateFileName = "Business-Report.xls";
string newFileName = String.Empty;
try
{
newFileName = excelExport.CopyTemplateFile(Server.MapPath("~/ExportTemplates/" + templateFileName));
excelExport.WriteData(forexOptionReport, newFileName);
Response.Clear();
Response.AddHeader("content-disposition", string.Format("Attachment; filename=\"{0}\"", "Business-Report" + ".xls"));
Response.ContentType = "application/vnd.ms-excel";
Response.TransmitFile(newFileName);
Response.Flush();
}
catch (Exception ex)
{
Errors.LogException("Error in Reports.BtnDownloadToExcel_Click", ex);
throw;
}
finally
{
if (!String.IsNullOrEmpty(newFileName))
{
excelExport.DeleteFile(newFileName);
}
}
MORE INFO
I've analyzed this with fiddler and this is what I see for the particular request/response which is expected to present the excel for download:
This Stackoverflow Q/A states that the meaning of the forbidden icon is that the client is terminating/aborting the response
I have found the solution to this issue. The details are as described in this link
This SO question has some details and resources that would clarify what was happening.
The basic issue is that IE versions 8 and below fail to download files over SSL when they see the following headers in the response:
Cache-control: no-cache
Pragma: no-cache
These headers should be removed and replaced with:
Response.Headers.Set("Cache-Control", "private, max-age=0");
I have a web page which I want people to be able to upload content to. (There will only be a small number of people using it, as it is access restricted, so I'm not too worried about any DOS type attacks.)
I'm using a fileUpload control to do this:
protected void Button1_Click(object sender, EventArgs e)
{
if (fileUploader.HasFile)
try {
fileUploader.SaveAs(Server.MapPath("Uploads\\") + fileUploader.FileName);
errorMessage.Text = "File name: " +
fileUploader.PostedFile.FileName + "<br>" +
fileUploader.PostedFile.ContentLength + " kb<br>";
}
catch (Exception ex) {
errorMessage.Text = "ERROR: " + ex.Message.ToString();
}
else
{
errorMessage.Text = "You have not specified a file.";
}
}
The files can be up to 50MB (I have changed the web.config to allow this). The problem I have is that with large files the user can't see the progress of the upload.
I want to know how I can display the progress on the page so the user can see something is happening. Not fussed about anything fancy - just something like:
bytes uploaded / total bytes
would be fine. I can get the total bytes using postedFile.ContentLength, but don't know how to get the bytes uploaded.
Also - am I able to refresh the screen as the upload is taking place?
Cheers,
Ben
This answer is not specific to ASP...
A file upload is typically done by making an HTTP POST request with Content-type: multipart/form-data. This includes the file body in one of the parts of the request body.
So within a given browser tab, there can only be one page loading at a given time. The short answer is, unless you get really fancy with iframes (one for status, one for upload), you will not be able to show the status.
However, if you use Flash, you can. http://www.uploadify.com/ is a great little front-end plugin (for jQuery) which allows the user to select multiple files, and uploads them all, showing the status along the way. I just plugged it into a site that limits uploads to 64M. Works awesome.
Your implementation is a synchronous operation which does not 'feedback' to the user about the file upload progress.
There are quite a few alternatives and 3rd party components, you might want to google them.
Here's one to start with: ASP.NET File Upload with Real-Time Progress Bar
I have used a couple of commercial components to do this:
Telerik and AjaxUPloader