Open PDF file with Save As option in asp.net webform - c#

I have list of PDF files on website (asp.net webforms). i want to open them with Save As option rather than it downlaods directly.
I tried to add download property to the link which didn't work. only was around seems to be HTTPHandler for *.pdf request.
I saw a piece of code for MVC based example here
return new FileStreamResult(stream, "application/pdf")
{
FileDownloadName = "file.pdf"
};
How can i convert this to HTTPHandler in as.net webform so that it open pdf files with Save As option.
I want to do it in a way so that when ever user click on any pdf file at that time Handler should come into action.
OR
I can create another file handlePDF.aspx and write code there also and will change link of pdf file to below
File One

If what you are trying to do is when they click on the file download link it pops up with save as or open dialog box, this is to do with the user's browser configuration. In the case of PDF's i believe Firefox has open in tab as the default option. If you try to push the file as a file stream it will more than likely just load it in a new tab as well.
tl;dr: Client side issue

You're on the right track. Serving PDF files are usually handled by an HttpHandler. That is, unless they can be served straight from the file system by the StaticHandler...
The key thing that is needed in order for the browser to raise the "Open or save" dialog is the Content-Disposition header in the response.
Here is an (untested) implementation that should get you on the right track:
public void ProcessRequest(HttpContext context)
{
string fileName = context.Request.QueryString["file"];
if(fileName == null || fileName == "")
{
throw new ArgumentException("The file argument cannot be null or empty");
}
// fetch file here from db/filesystem/other storage
byte[] fileBytes = LoadFileBytes(fileName);
context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
context.Response.ContentType = "application/pdf";
context.Response.BinaryWrite(fileBytes);
}
If you want to avoid buffering the whole file in memory, this might also work (requires .Net 4.0 for the CopyTo method on the stream):
public void ProcessRequest(HttpContext context)
{
string fileName = context.Request.QueryString["file"];
if(fileName == null || fileName == "")
{
throw new ArgumentException("The file argument cannot be null or empty");
}
// fetch file stream from db/filesystem/other storage
Stream fileStream = GetFileStream(fileName);
context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
context.Response.ContentType = "application/pdf";
fileStream.CopyTo(context.Response.OutputStream);
}

Related

C# download button folder path

This question was migrated from Super User because it can be answered on Stack Overflow.
Migrated 14 days ago.
This is a C# code for a Web Form page named "upload.aspx" which allows the user to upload a PDF file and store it in the server. The file uploaded must be a PDF file, and all the text boxes must be filled before submission. The file name is saved in the database as a string with the format of "GUID.pdf", Guid.NewGuid().ToString().
tTR.FileName = Guid.NewGuid().ToString() + ".pdf";
dataBaseDataContext.TTRs.InsertOnSubmit(tTR);
dataBaseDataContext.SubmitChanges();
String path = Server.MapPath("Attachments/" + tTR.FileName);
FileUploadtoServer.SaveAs(path);
Response.Write("<script>alert('Successfully Inserted!')</script>");
Invoice.Text = "";
Manufacture.Text = "";
HeatCode.Text = "";
Description.Text = "";
PO_Number.Text = "";
i created a search function that allows the user to search for based on Heat Code, Item Code, PO Number, and Description. he user can also edit and download the file by clicking on the "Edit / Download" link. The problem here is in my Download button. It's not downloading/ able to read the path. i can see the pdf exist in the Attachment folder but it's not able to find the correct file name associated to the heat code.
private void BindData(List<TTR> Data)
{
try
{
if (Data.Count > 0)
{
StringBuilder append = new StringBuilder();
foreach (TTR tTR in Data)
{
string PdfGuid = tTR.FileName;
append.Append("
}
tdList.InnerHtml = append.ToString();
}
}
catch (Exception)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
try
{
string filePath = Server.MapPath("~/Attachments/" + filename + ".pdf");
byte[] content = File.ReadAllBytes(filePath);
Response.Clear();
Response.ContentType = "application/pdf";
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename + ".pdf");
Response.Buffer = true;
Response.BinaryWrite(content);
Response.End();
}
catch (Exception)
{
This is a C# code for a web form page named "upload.aspx" that allows a user to upload a PDF file, store it on the server, and save its file name in the database as a string with the format "GUID.pdf", where GUID is a unique identifier generated using Guid.NewGuid().ToString(). Before submission, all the text boxes must be filled, and the uploaded file must be a PDF.
The code also includes a search function that allows the user to search for files based on Heat Code, Item Code, PO Number, and Description. The user can also edit and download the file by clicking on the "Edit / Download" link. However, the download button is encountering issues as it is not able to find the correct file name associated with the heat code and download the file.
The problem seems to be with the code that retrieves the file path, reads the contents of the file, sets the content type as "application/pdf", and writes the contents to the response stream. The code is trying to read the file from the server's "Attachments" folder using the file path, but it seems to be encountering issues finding the correct file.

Download a Large file Async in ASP.NET C#

I have the code below which works well for small files but for large files it generates the zip as required but doesn't download it. I get all sorts of errors including Timeout (which I have managed to resolve). The other problem is that it runs in Sync. The largest file I have generated myself is a 330MB zip file with about 30 HD images attached to it. But this can even go to GBs as the user can choose to download about 100 or even more HD images at once.
To resolve both issues, I thought downloading in async may help in both cases. I want to alert the user that their download has started, and that they will be notified when it is ready.
I am thinking of sending the stream down if the client IsConnected (then delete the file) or sending an email to ask them to download the file if they have decided to logout (then delete the file using the offline download link). I just don't know where or how to write async code, or if what I want to do can actually be done if the user decides to logout.
Here's my current code:
private void DownloadFile(string filePath)
{
FileInfo myfile = new FileInfo(filePath);
// Checking if file exists
if (myfile.Exists)
{
// Clear the content of the response
Response.ClearContent();
// Add the file name and attachment, which will force the open/cancel/save dialog box to show, to the header
Response.AddHeader("Content-Disposition", "attachment; filename=" + myfile.Name);
// Add the file size into the response header
Response.AddHeader("Content-Length", myfile.Length.ToString());
// Set the ContentType
Response.ContentType = "application/octet-stream";
Response.TransmitFile(filePath);
Response.Flush();
try
{
myfile.Delete();
}
catch { }
}
}
I don't know about Async downloads from asp.net applications so I can't address that question. But I have run into enough download issues to always start from the same place.
First, download from a generic handle (ASHX) and not a web form. The webform wants to do extra processing at the end of the request that can cause problems. You question didn't state if you are using a web form or generic handler.
Second, always end the request with the ApplicationInstance.CompleteRequest() method call. Don't use Request.Close() or Request.End()
Those two changes have often cleaned up download issues for me. Try these change and see if you get the same results. Even if you do get the same results this is a better way of coding downloads.
Finally, as an aside, only catch appropriate exceptions in the try-catch bock.
Your code would be like this:
public class Handler1 : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
// set from QueryString
string filePath = "...";
FileInfo myfile = new FileInfo(filePath);
// Checking if file exists
if (myfile.Exists)
{
// Clear the content of the response
context.Response.ClearContent();
// Add the file name and attachment, which will force the open/cancel/save dialog box to show, to the header
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + myfile.Name);
// Add the file size into the response header
context.Response.AddHeader("Content-Length", myfile.Length.ToString());
// Set the ContentType
context.Response.ContentType = "application/octet-stream";
context.Response.TransmitFile(filePath);
context.Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
try
{
myfile.Delete();
}
catch (IOException)
{ }
}
}
public bool IsReusable
{
get
{
return false;
}
}
}

Download PDF file from Web location and Prompt user SaveAs box on client in web-Application ASP C#

I have link of a PDF file located on a website e.g. (https://www.mysite.com/file.pdf).
What I need is prompt the user (on Client side) the SaveAs box to choose the file location to save the file.
I tried the SaveFileDialog , but got know that it is only for Windows Forms. and my application is web based.
C# Code
var fileNumber = lblFileNumber.Text;
string fileDownloadLink = "http://www.mysite.com/" + fileNumber + ".pdf";
string fileName = fileNumber + ".pdf";
bool exist = false;
try
{
var request = (HttpWebRequest)System.Net.WebRequest.Create(fileDownloadLink);
using (var response = (HttpWebResponse)request.GetResponse())
{
exist = response.StatusCode == HttpStatusCode.OK;
}
}
catch
{
}
if (exist)
{
var wClient = new WebClient();
wClient.DownloadFile(fileDownloadLink, fileName);
}
I wrote the above code, it does check if the file is exist on the file location, but
how to prompt user to choose the location to where he want to save file and save on his local hard drive?
It is not possible to do that. When the user wants to download a file, the browser will decide how to show it to the user.
Write a file from disk directly:
HttpContext.Current.Response.TransmitFile(#"C:\yourfile.pdf");
Or from another source, loaded as a byte array:
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.BinaryWrite(bytesOfYourFile);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();

How to show download dialog before file is ready to download?

I'm getting a file from a database in byte [] format and want user to see download dialog before Linq will take it from the database. It's in C# and ASP.NET.
Now, it's like this:
User choose a file, click on it.
In code I get id of file clicked and using Linq I'm downloading.
Then I send the file by Response.OutputStream.Write(content, 0,
content.Length);
Before a file is downloaded from the database user won't see any
download dialog.
What can I do if I want users to see the download dialog before file is downloaded?
Code:
Getting file by id:
public static byte[] getFile(Guid id)
{
var linqFile = from file in MyDB.Files
where file.IdPliku.Equals(id)
select new
{
Content = file.Content
};
return linqFile.ToList().FirstOrDefault().Content.ToArray();
}
Saving file:
public void SaveFile(Guid fileID, string filename, string mimeTypes)
{
try
{
byte[] content = FileService.getFile(fileID);
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = mimeTypes;
Response.AppendHeader("Accept-Ranges", "bytes");
Response.AppendHeader("Content-Range", string.Format("0-{0}/{1}", content.Length, content.Length));
Response.AppendHeader("Content-Length", content.Length.ToString());
Response.AppendHeader("Content-Encoding", "utf-8");
Response.AppendHeader("Content-Type", Response.ContentType);
Response.AppendHeader("Content-Disposition", "attachment; filename= " + HttpUtility.UrlEncode(filename));
Response.OutputStream.Write(content, 0, content.Length);
//Response.BinaryWrite(content);
Response.Flush();
}
finally
{
Response.Close();
}
}
You are my hope.
your issue is here:
byte[] content = FileService.getFile(fileID);
because in this line you allocate the whole file in the web server's RAM and put everything in there, all content of the file from the database; what happens later does not matter anymore because you have already downloaded from db to web server in this line!!!
I am having such Deja-vu because I am sure I have given exactly the same comment on a very same question few weeks ago. Can't find it now, search for something like this here in SO.
In fact the solution is to stream directly to the output stream of the Response avoiding your byte[] array allocation above, to get this your data layer should of course support it and if it does not you could add a method for this. You want to use SQL Server filestream or something similar.

MVC C# Download file and save as dialog

Hi all wondering if someone can help; i've written this code which will generate an excel spreadsheet and save it to a specified location. I want to then display a "Save as" dialogue box by reading the file from the stored location and then asking then user where they want to store it. The excel file is being generated fine and i can open it normally! However my problem is the code i've written seems to be outputting the file directly to my browser, so i get all the contents of the excel file on my browser screen, not displaying the save as dialogue box as expected!
public ActionResult FormSuccess()
{
String FileName = System.Configuration.ConfigurationManager.AppSettings["FileName"].ToString();
String FilePath = System.Configuration.ConfigurationManager.AppSettings["FileSaveLocation"].ToString();
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "application/vnd.xls";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath + FileName);
response.End();
return PartialView("FormSuccess");
}
Yo Vince, how's tricks? Still wearing the medallion? :)
Shouldn't you be using FileContentResult instead of PartialView? You won't be able to return the file AND the HTML "success" content in the same call - you should probably call the PartialView first, which would then use javascript to open the FileContentResult URL in a new window.
See this: http://www.mikesdotnetting.com/Article/125/ASP.NET-MVC-Uploading-and-Downloading-Files
and this url as well :
http://weblogs.asp.net/rajbk/archive/2010/05/03/actionresult-types-in-mvc2.aspx
I think that your problem is that you return PartialView. Let me give you small exmaple of my implemetation:
public ActionResult FileXls()
{
var output = new MemoryStream();
var writer = new StreamWriter(output);
//create your workbook excel file
....
//workbook.Save(output);
writer.Flush();
output.Position = 0;
return File(output, "text/excel", "file.xls");
}

Categories