Download PDF File in C# - c#

In my application I want to give user the option to download a PDF file. In my code, the file gets opened by browser; however, I want the file to be downloaded. Here's my code:
Controller
string name = id; //id is the name of the file
string contentType = "application/pdf";
var files = objData.GetFiles(); //list of files
string filename = (from f in files
orderby f.DateEncrypted descending
where f.FileName == name
select f.FilePath).First(); //gets the location of the file
string FullName = (from f in files
where f.FileName == name
select f.FileName).First(); //gets the new id in new location to save the file with that name
//Parameters to File are
//1. The File Path on the File Server
//2. The content type MIME type
//3. The parameter for the file save by the browser
return File(filename, contentType, FullName);
Here's how I'm using it in dropdown menu.
View:
<li><a id="copyURL" href="#Url.Action("Download", "Home", new { id = item.FileName})">Download</a></li>
By clicking on "Download", the file gets opened browser.

Set your content type to "application/octet-stream" so the PDF plugin won't try to pick it up and display it. Then the browser will handle it as a file download.

Download Files from Web:
This example shows how to download files from any website to local disk. The simply way how to download file is to use WebClient class and its method DownloadFile. This method has two parameters, first is the url of the file you want to download and the second parameter is path to local disk to which you want to save the file.
Download File Synchronously
The following code shows how to download file synchronously. This method blocks the main thread until the file is downloaded or an error occur (in this case the WebException is thrown).
[C#]:
using System.Net;
WebClient webClient = new WebClient();
webClient.DownloadFile("pdf file address", #"c:\myfile.pdf");
Download File Asynchronously:
To download file without blocking the main thread use asynchronous method DownloadFileA­sync. You can also set event handlers to show progress and to detect that the file is downloaded.
[C#]:
private void btnDownload_Click(object sender, EventArgs e)
{
WebClient webClient = new WebClient();
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
webClient.DownloadFileAsync(new Uri("pdf file address"), #"c:\myfile.pdf");
}
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
private void Completed(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("Download completed!");
}
ref: http://www.csharp-examples.net/download-files/

Browser will try to show the file unless you specify not to.
Try Adding ContentDisposition before returning File.
var cd = new System.Net.Mime.ContentDisposition
{
FileName = filename,
Inline = false,
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(filename, contentType, FullName);

Related

Can't get File to download into Fiddler2 Folder

So, I have this code i am programming under a button. When pressed, the user is asked if they want to download the newest File. If yes, then download it and the download location is supposed to be: Documents\Fiddler2 (You Get this Folder created when Installing Fiddler Classic).
However, after several different attempts, the file is only downloaded to the Documents Folder and needs to download to the Documents\Fiddler2 Folder. What am I doing wrong?
private void button4_Click(object sender, EventArgs e)
{
string title = "Check For New Version.";
string question = "Would you like to Check for any Updates?";
string url = "www.google.com";
if (DialogResult.Yes ==
MessageBox.Show(this, question, title,MessageBoxButtons.YesNo,MessageBoxIcon.Question))
{
string path = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string path2 = Path.Combine(path, #"Fiddler2");
MessageBox.Show(path2);
Directory.SetCurrentDirectory(path2);
using (var client = new WebClient())
{
client.DownloadFile("https://drive.google.com/file/d/13K2IEH-FNQ2HhqAlvaYO3sEZoeWOtPMN/view?usp=sharing", "test.png");
}
}

How do I download a file given the URL in C#

I am trying to download a file from a URL and I want to have a Popup where I can decide where to save the file on my pc. I know how to save it to a setlocation but that's not what I want.
WebClient webClient = new WebClient();
webClient.DownloadFileAsync(new Uri("URL"), #"d:\location");
So I get that this is how I download it so a set location but I need to be able to save it to a location of choice with the usual popup you normally get when you download anything.
To give more sight into this I have 2 radiobuttonlists in which the user can check what topics he wants then he can choose from a dropdownlist which file he wants to download and then he click on a downloadbutton which should trigger the download of that file.
Use DownloadFileAsync and listen to DownloadFileFinished. First download it to temp file and at event DownloadFileFinished, show popup and ask where to save. Then just copy the file from temp file to the filename from user.
-or-
Show SaveFileDialog before you start DownloadFileAsync.
Talking about a desktop app you can use SaveFileDialog.
The msdn code example:
private void button1_Click(object sender, System.EventArgs e)
{
Stream myStream ;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*" ;
saveFileDialog1.FilterIndex = 2 ;
saveFileDialog1.RestoreDirectory = true ;
if(saveFileDialog1.ShowDialog() == DialogResult.OK)
{
if((myStream = saveFileDialog1.OpenFile()) != null)
{
// Code to write the stream goes here.
myStream.Close();
}
}
}

How to generate txt file then force download in ASP.NET Web Forms?

I need to set a handler to <asp:Button> element. When user clicks, txt file must be generated in code-behind and must be automatically downloaded by user. There is no need to get any data from user. All file content will be generated in code behind. For example, how to return to user a txt file with content of this variable:
string s = "Some text.\nSecond line.";
For this kind of job you should create file on the fly.
Please see the code:
protected void Button_Click(object sender, EventArgs e)
{
string s = "Some text.\r\nSecond line.";
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=testfile.txt");
Response.AddHeader("content-type", "text/plain");
using (StreamWriter writer = new StreamWriter(Response.OutputStream))
{
writer.WriteLine(s);
}
Response.End();
}
}
Just note for new line you need to use \r\n instead of only \n or use WriteLine function for each line
You can simply generate the file on the server side and then push it down to the user. s would be the content of the File that you will generate.
Creating the File
Creating a new File is as simple as writing the data to it,
// var s that you're having
File.Create(Server.MapPath("~/NewFile.txt")).Close();
File.WriteAllText(Server.MapPath("~/NewFile.txt"), s);
This will create a new file (if doesn't exist) and write the content of the variable s to it.
Pushing it down to the user
You can allow the user to download it, using the following code,
// Get the file path
var file = Server.MapPath("~/NewFile.txt");
// Append headers
Response.AppendHeader("content-disposition", "attachment; filename=NewFile.txt");
// Open/Save dialog
Response.ContentType = "application/octet-stream";
// Push it!
Response.TransmitFile(file);
This will let him have the file you just created.
I do have a similar case but a little bit more complex usecase.
I do generate different types of files. I wrote a container class Attachment witch holds the content type and the value of the generated file as an Base64 string.
public class Attachment {
public string Name {get;set;}
public string ContentType {get;set;}
public string Base64 {get;set;}
}
This enables me to serve different file types with the same download method.
protected void DownloadDocumentButton_OnClick(object sender, EventArgs e) {
ASPxButton button = (ASPxButton) sender;
int attachmentId = Convert.ToInt32(button.CommandArgument);
var attachment = mAttachmentService.GenerateAttachment(attachmentId);
Response.Clear();
Response.AddHeader("content-disposition", $"attachment; filename={attachment.Name}");
Response.AddHeader("content-type", attachment.ContentType);
Response.BinaryWrite(Convert.FromBase64String(attachment.Base64));
Response.End();
}

Upload form not working - File is being used by another process

I've got a C# file upload that is meant to extract XML tags from inside a DocX document, the problem I'm facing is that when the file is uploaded, the error "File is being used by another process" comes up. Attempting to delete the document shows it is being used by IIS process manager.
Is there a way to stop my code to get it to continue running?
<script runat="server">
//foreach (DataRow row in table.Rows)
//{
// string dbColumnNames = (selectedData.ToString());
//send files
//}
public string _TempFileLocation = ""; //Used to locate Word Document File Path
//THE USER UPLOAD CONTROL. users use this to upload the document to the server
public void XMLextractor(string _filePath)
{
//XML extraction code
displayFilepath.Text = _filePath;
_TempFileLocation = _filePath;
}
//names the script manager which will be used when the user attempts to upload a form / gives an error if they incorrectly attempt to upload
protected void UploadButton_Click(object sender, EventArgs e)
{
//if file is located
if (FileUploadControl.HasFile)
{
try
{
//allow content type of document / docx
if (FileUploadControl.PostedFile.ContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
{
if (FileUploadControl.PostedFile.ContentLength < 10485760) // 10mb)
{
//name the filename, find the path of the name
string filename = Path.GetFileName(FileUploadControl.FileName);
//path of server upload (we just need to save it as a variable to be found on the next page, as it will be made / deleted
FileUploadControl.SaveAs(Server.MapPath("~/") + filename);
//update the label with file uploaded
StatusLabel.Text = "Upload status: File uploaded!";
XMLextractor(Server.MapPath("~/") + filename);
//move onto template wizard page
//Response.Redirect("http://portal.acoura.com/admin/templatewizard.aspx", false);
WordprocessingDocument _TempDoc = WordprocessingDocument.Open(Server.MapPath("~/") + filename, true);
XDocument xdoc = XDocument.Load(Server.MapPath("~/") + filename);
//query to find particular descendants
var lv1s = from document in xdoc.Descendants("table")
select new
{
Header = document.Attribute("name").Value,
Children = document.Descendants("tag")
};
//Loop through results
StringBuilder result = new StringBuilder();
foreach (var lv1 in lv1s)
{
result.AppendLine(lv1.Header);
foreach (var lv2 in lv1.Children)
result.AppendLine(" " + lv2.Attribute("name").Value);
}
//the label should contain the content controls of the document, using the class, XMLfromDocument
labelContentControls.Text = fileUpload_Displayx(XMLfromDocument.GetContentControls(_TempDoc));
}
else
//display the size the file needs to be less than
StatusLabel.Text = "Upload status: The file has to be less than 10mb!";
}
else
//tell the user only docx files are accepted
StatusLabel.Text = "Upload status: Only DOCX files are accepted!";
}
catch (Exception ex)
{
//display the exception message, in which case it would be either size / type / if it's present
StatusLabel.Text = "Upload status: The file could not be uploaded. The following error occured: " + ex.Message;
}
}
}
//needs to be replaced with the variable found in descendants / var tagContent
public string fileUpload_Displayx(XElement _contentcontrol)
{
string str = "";
str = _contentcontrol.Name.ToString();
return str;
}
//public static displayDatabase(object sender, EventArgs e)
// {
//}
//run the validate button on templatewizard, will mark up any problems or give green light
//if red, allow users to replace fields in the left column, from ones in the atabase on the right
//display upload button when validation is succesful. When Upload button runs, Take to new
// / existing page of reports, allow users to download this
</script>
You are opening the file without closing it on this line:
WordprocessingDocument _TempDoc = WordprocessingDocument.Open(Server.MapPath("~/") + filename, true);
Then you are opening it again with xDocument.Load():
XDocument xdoc = XDocument.Load(Server.MapPath("~/") + filename);
I assume that is where the error occurs.
If you handle all of the stuff XDocument needs to do first, and then open and close the WordProcessingDocument.Open() line to get the content controls, you should be fine.
Basically only one process can have a open and read or modify a file at a time, so if two operations from two different sources need to be performed, they must be performed sequentially on the file.
You can also open the file via a FileStream and then load the content into memory and into your XDocument, therefore negating the need to have the file opened twice by XDocument and WordProcessingDocument simultaneously.
Hope this helps!

Manipulate .html file from code-behind

I have an html file in my asp.net webforms project that people can download when clicking a button.
I would like to generate some <select> lists and append to certain parts of the html based on some database values before the file gets sent to the user. Is this possible using c#? My current download functionality:
public void DownloadOfflineAuditSheetEditor(object s, EventArgs e)
{
Response.AppendHeader("content-disposition", "attachment; filename=thefile.html");
Response.WriteFile(Server.MapPath("~/thefile.html"), true);
Response.End();
}
Yes - you'd have to manipulate "the file" before it gets sent to the user.
In your method DownloadOfflineAuditSheetEditor you could have call a new method that reads the current file, gets the contents from the DB and then writes to the file or a new file, for example:
public void GenerateRealTimeContent()
{
var path = Server.MapPath("~/thefile.html");
var dbContent = Database.GetContent(); // returns the <select> Options
string[] lines = System.IO.File.ReadAllLines(path);
StringBuilder sb = new StringBuilder();
foreach (var line in lines)
{
if (line == "CONTENT WHERE YOU WANT TO EDIT")
{
SB.AppendLine(dbContent);
}
SB.AppendLine(line);
}
// code to write to your file
}
Then in your original function do:
public void DownloadOfflineAuditSheetEditor(object s, EventArgs e)
{
GenerateRealTimeContent();
Response.AppendHeader("content-disposition", "attachment; filename=thefile.html");
Response.WriteFile(Server.MapPath("~/thefile.html"), true);
Response.End();
}
http://msdn.microsoft.com/en-us/library/ezwyzy7b.aspx - Reading from a file
http://msdn.microsoft.com/en-us/library/aa287548(v=vs.71).aspx - Write to a file
You can read the file with a StreamReader, edit it or add anything and write the all thing in the Resposne.

Categories

Resources