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.
Related
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);
}
I have a grid that lists the uploaded documents for each record in another table. When I click View in the grid, while the app is on my local machine, it opens the pdf from sql server with no problem. When I push it over to the dev server and I click View, it kind of just freezes up the application for a minute or so. I'm not quite sure what's going on here, though I suspect that the method is possibly trying to run the pdf ON the server instead of my machine?
protected void UploadedDocumentsRadGrid_ItemCommand(object sender, GridCommandEventArgs e)
{
if(e.CommandName == "ViewDoc")
{
if(e.Item is GridDataItem)
{
GridDataItem item = (GridDataItem)e.Item;
var doc = from d in db.UploadedDocuments
where d.ID.ToString() == item["ID"].Text
select d;
foreach(var Doc in doc)
{
string filePath = Path.GetTempFileName();
File.Move(filePath, Path.ChangeExtension(filePath, ".pdf"));
filePath = Path.ChangeExtension(filePath, ".pdf");
File.WriteAllBytes(filePath, Doc.DocumentData.ToArray());
OpenPDFFile(filePath);
}
}
}
}
protected void OpenPDFFile(string filePath)
{
using(System.Diagnostics.Process p = new System.Diagnostics.Process())
{
p.StartInfo = new System.Diagnostics.ProcessStartInfo(filePath);
p.Start();
p.WaitForExit();
try
{
File.Delete(filePath);
}
catch { }
}
}
Further Explanation:
This application allows users to upload scanned documents into a SQL table. If the user needs to view an uploaded document, they should be able to click on that document in the grid and that document should then open on their local machine. Am I not going about this the right way?
UPDATE:
Everything is working as needed now. A big thank you to Sunil for the code they provided for me. I did have to change the SQL connection to a LINQ to SQL statement, which was no big deal. The final code is below:
var doc = from d in db.UploadedDocuments
where d.ID.ToString() == Session["ID"].ToString()
select d;
foreach (var Doc in doc)
{
byte[] bytes = Doc.DocumentData.ToArray();
this.Page.Response.Buffer = true;
this.Page.Response.Charset = "";
this.Page.Response.ClearContent();
if (this.Page.Request.QueryString["download"] == "1")
{
this.Page.Response.AppendHeader("Content-Disposition", "attachment; filename=PDF.pdf");
}
this.Page.Response.Cache.SetCacheability(HttpCacheability.NoCache);
this.Page.Response.ContentType = "application/pdf";
this.Page.Response.BinaryWrite(bytes);
this.Page.Response.Flush();
this.Page.Response.End();
As suggested by Paddy you need to set the mime type from your code.
In your case, if filePath points to a file like c:\myfiles\pdfs\abc.pdf then you can use the first code snippet, but if it the filePath is like ~/files/abc.pdf i.e. the pdf file is stored somewhere under the website root folder then use the second code snippet. I am not sure why you would like to delete the file after it's opened in a browser.
When filePath is an absolute or UNC path
protected void OpenPDFFile(string filePath)
{
//set the appropriate ContentType.
Response.ContentType = "Application/pdf";
//write the file to http content output stream.
Response.WriteFile(filePath);
Response.End();
}
When filePath is an web path like ~/mypfile.pdf
protected void OpenPDFFile(string filePath)
{
//set the appropriate ContentType.
Response.ContentType = "Application/pdf";
//get the absolute file path
filePath = MapPath(filePath);
//write the file to http content output stream.
Response.WriteFile(filePath);
Response.End();
}
UPDATE 1
From what you are saying, you want to delete files on a user's local computer from a remote web server since the web app code executes in a remote server. This is absolutely not possible, and even if it was, it would be a BIG security risk since a remote computer would then be controlling an end-user's computer. So, I suggest you follow the normal practice in a web app for streaming files to an end-user's computer.
If you have files stored in database then you could use code below to open a pdf file on end-user's computer. The end user would click on the file link in your gridview and the link click code on server-side would then execute to stream the pdf file to user's computer. Note that the link for file in your gridview should be a link button with a command argument equal to uploadfileId column value for that upload.
I have assumed that in your database there is a table Uploads that has these columns - UploadId, FileData, FileName, FileContentType with UploadId being an auto-incrementing primary key.
Markup for Link in GridView that will download pdf when clicked
<asp:TemplateField ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:LinkButton ID="lnkViewPdfFile" runat="server" Text="View Pdf" OnClick="ViewPdfFile" CommandArgument='<%# Eval("UploadId") %>'></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
Click event for above file LinkButton in code-behind
protected void ViewPdfFile(object sender, EventArgs e)
{
int uploadId = int.Parse(btn.CommandArgument);
byte[] bytes;
string fileName, contentType;
string conString = ConfigurationManager.ConnectionStrings["appdatabase"].ConnectionString;
using (SqlConnection con = new SqlConnection(conString))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "SELECT FileName, FileData, ContentType FROM Uploads WHERE UploadId=#uploadId";
cmd.Parameters.AddWithValue("#uploadId", uploadId);
cmd.Connection = con;
con.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
sdr.Read();
bytes = (byte[])sdr["FileData"];
contentType = sdr["ContentType"].ToString();
fileName = sdr["FileName"].ToString();
}
con.Close();
}
}
context.Response.Buffer = true;
context.Response.Charset = "";
if (context.Request.QueryString["download"] == "1")
{
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
}
context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.ContentType = "application/pdf";
context.Response.BinaryWrite(bytes);
context.Response.Flush();
context.Response.End();
}
You are writing server side code. You may find that there are a number of open PDF's on your web server (although your generic 'catch and swallow' handling may be masking any problems there). You need to stream the file data to your client, with the appropriate mime type.
It works locally, as your web server is the same as the machine on which you open the browser when developing.
Hard to exactly duplicate your code, as you are opening multiple PDF files - you may find it better to open these in another window rather than serving them directly on postback like this.
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();
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.
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");
}