Download Button to download from picture library - asp.net

I have a ListView with a picture library as source and for each picture I have a asp:LinkButton that represents a download button. When pressed my button should open the browser download box. I'm using the following code to achieve that:
public void Download_Click(object source, EventArgs e)
{
LinkButton button = (LinkButton)source;
string url = Server.UrlEncode(button.CommandArgument);
FileInfo fileInfo = new FileInfo(url);
if (fileInfo.Exists)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fileInfo.Name);
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.ContentType = "application/octet-stream";
Response.Flush();
Response.WriteFile(fileInfo.FullName);
}
else
{
//error
}
}
On that code I'm using Server.Encode("fileName") but I tried Server.Map and also used the "PicLibraryName/FileName" and "Application/PictureLibraryName/FileName" but I never get FileInfo.Exists true because I always get FileNotFoundException or System.Web.HttpException (when I use a virtual path).
Anyone knows what's the best way to solve this problem?

I think you should use WebClient.DownloadData(url) for downloading the file and then Response.OutputStream.Write method for output downloading data, also don't forget to end response using Response.End() something like this:
var wc=new System.Net.WebClient();
var data=wc.DownloadData(url);
Response.Clear();
//add headers..
Response.OutputStream.Write(data);
Response.End();

Related

Download popup not coming properly in asp.net page load

I am trying to open the file based on the below code.
I am not using server.mappath. because, the access path is direct file server path and it is mapped with service account.
protected void Page_Load(object sender, EventArgs e)
{
string filePath1 = #"\\RMN\T001\PROC\MATERIALDB\";
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=" + "MAT01210821.png");
Response.WriteFile(filePath1);
Response.ContentType = "";
Response.End();
}
I am getting below error.
The filename, directory name, or volume label syntax is incorrect.
My requirement is, when i execute the above code, it should ask popup to end user "Do you want to open or save the file ..."? below screenshot for reference.
enter image description here
Even though the actual error is missing, the line Response.WriteFile(filePath1); is trying to use a folder as if it was a file.
To avoid such confusion, the folder path should be stored in a variable named folder and used to construct the actual path.
var folder = #"\\RMN\T001\PROC\MATERIALDB\";
var fileName="MAT01210821.png";
var filePath=Path.Combine(folder, fileName) ;
...
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
Response.WriteFile(filePath);

Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack

I have download link present in grid view and when I click on it, a save dialogue pop up will appeared and an Excel fill will be downloaded.
But I am getting error "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack." on Response.End().
Code :
protected void grdFiles_RowCommand(object sender, GridViewCommandEventArgs e)
{
try
{
if (e.CommandName == "download")
{
string _FileName = Convert.ToString(e.CommandArgument);
//Response.Clear();
//Response.AppendHeader("Content-Disposition", "attachment; filename=" + _FileName);
//Response.ContentType = "application//octet-stream";
//Response.TransmitFile(Server.MapPath("~/Files/" + _FileName));
//Response.End();
// Get the physical Path of the file(test.doc)
string filepath = Server.MapPath("test.doc");
// Create New instance of FileInfo class to get the properties of the file being downloaded
FileInfo file = new FileInfo(Server.MapPath("~/Files/" + _FileName));
// Checking if file exists
if (file.Exists)
{
// Clear the content of the response
Response.ClearContent();
// LINE1: Add the file name and attachment, which will force the open/cance/save dialog to show, to the header
Response.AddHeader("Content-Disposition", "attachment; filename=" + file.Name);
// Add the file size into the response header
Response.AddHeader("Content-Length", file.Length.ToString());
// Set the ContentType
Response.ContentType = "application/vnd.ms-excel";
// Write the file into the response (TransmitFile is for ASP.NET 2.0. In ASP.NET 1.1 you have to use WriteFile instead)
Response.TransmitFile(file.FullName);
// End the response
Response.End();
}
}
}
catch (Exception ex)
{
}
}
Another possible cause of this error, could possibly be because your grid is in an update panel?
If this is the case I would recommend that you add your grid control as a Post back trigger as such:
<asp:UpdatePanel runat="server" ID="UpdatePanel1">
<Triggers>
<asp:PostBackTrigger ControlID="grdFiles" />
</Triggers>
<ContentTemplate>
<gridview ID="grdFiles" runat="server">
your grid view content
</gridview>
</ContentTemplate>
</asp:UpdatePanel>
Though putting an entire grid as a Post back trigger might be overkill (post backs on paging might occur etc.), you could try creating your download link as a template column and set the control inside the grid as the post back trigger.
I had a similar problem where I used an Export button as a download button instead, and use the grid command to select a detail and make this button available only when something in the grid is selected then place a post back trigger on this button instead of having it on the grid.
this is because of ThreadAbortException. try to handle this specific exception.
try
{
if (file.Exists)
{
//do something
}
response.End();
}
catch (ThreadAbortException ex)
{
//Log trace info
}
There is a handy way to deal with "Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack." issues. You need to write on the Output window.
Add using System.Diagnostics;
Add a Try/Catch for the line that is erroring
In the Catch add these lines
try
{ ..}
catch(Exception ex)
{
Debug.WriteLine(ex.Message);
Debug.WriteLine(ex.StackTrace);
Debug.WriteLine(ex.InnerException.ToString());
}
Just debug and check the Output window
Hope it helps.
Store the file path in Web.Config file and try this code:
string filename = "test.doc";
string FilePath = ConfigurationManager.AppSettings.Get("SharedPath") + ConfigurationManager.AppSettings.Get("Path") + "\\\\" + filename;
FileInfo file = new FileInfo(FilePath);
if (file.Exists)
{
Response.AppendHeader("content-disposition",
"attachment; filename=" + filename);
Response.ContentType = "application/download";
Response.WriteFile(FilePath);
Response.End();
}

ASP.Net Transmit File

I am writing a webapplication in ASP.net.
I am trying to make a file dialog box appear for downloading something off the server.
I have the appropriate file data stored in a variable called file.
File has fields:
FileType - The MIMEType of the file
FilePath - The server-side file path
Here's the code so far:
Response.Clear();
Response.ContentType = file.FileType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + GetFileName(file));
Response.TransmitFile(file.FilePath) ;
Response.End();
GetFileName is a function that gets me the filename from an attachment object. I only store the path.
The above code is in a function called "Download_Clicked" that is an event that triggers on click. The event is mapped to a LinkButton.
The problem is that when I run the above code, nothing happens. The standard dialog box does not appear.
I have attempted the standard trouble-shooting such as making sure the file exists, and ensuring the path is correct. They are both dead on the mark.
My guess is that because my machine is also the server, it may not be processing properly somehow.
Thanks in advance.
Edit 1: Attempted putting control onto another page, works fine.
Edit 2: Resolved issue by removing control from AJAX Update Panel.
I've found another to do this without removing the update panel. Place the code below in your page load and you'll now be able to use that button to trigger a download.
ScriptManager.GetCurrent(this.Page).RegisterPostBackControl(Button);
Use Response.WriteFile() instead.
Also, don't use Response.End()! This aborts the thread. Use Response.Flush(); Response.Close();
Try changing
Response.AppendHeader("Content-Disposition", "attachment; filename=" + GetFileName(file));
To
Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(GetFileName(file))));
If that doesn't work, you can always use Response.BinaryWrite or Resonse.Write to stream the file to the web browser
Here is how transmit the file using Response.Write or Response.BinaryWrite. Put these functions in a library somewhere then call them as needed
public void SendFileToBrowser(String FileName, String MIMEType, String FileData)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.ContentType = MIMEType;
Response.Buffer = true;
Response.Write(FileData);
Response.End();
}
public void SendFileToBrowser(String FileName, String MIMEType, Byte[] FileData)
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + FileName);
Response.ContentType = MIMEType;
Response.Buffer = true;
Response.BinaryWrite(FileData);
Response.End();
}
Then somewhere you call these functions like so
SendFileToBrowser("FileName.txt", "text/plain", "Don't try this from an Update Panel. MSAjax does not like it when you mess with the response stream.");
See edit on initial post.
Removed Ajax Update Panel to resolve the error. The panel was stopping the post back to the server.
For more info, see Cris Valenzuela's comment.

What am I doing wrong with HttpResponse content and headers when downloading a file?

I want to download a PDF file from a SQL Server database which is stored in a binary column. There is a LinkButton on an aspx page. The event handler of this button looks like this:
protected void LinkButtonDownload(object sender, EventArgs e)
{
...
byte[] aByteArray;
// Read binary data from database into this ByteArray
// aByteArray has the size: 55406 byte
Response.ClearHeaders();
Response.ClearContent();
Response.BufferOutput = true;
Response.AddHeader("Content-Disposition", "attachment; filename=" + "12345.pdf");
Response.ContentType = "application/pdf";
using (BinaryWriter aWriter = new BinaryWriter(Response.OutputStream))
{
aWriter.Write(aByteArray, 0, aByteArray.Length);
}
}
A "File Open/Save dialog" is offered in my browser. When I store this file "12345.pdf" to disk, the file has a size of 71523 Byte. The additional 16kB at the end of the PDF file are the HTML code of my page (as I can see when I view the file in an editor). I am confused because I was believing that ClearContent and ClearHeaders would ensure that the page content is not sent together with the file content.
What am I doing wrong here?
Thanks for help!
I think you want a Response.End at the end of this method.
In a quick glance, you're missing Response.End();

Zipping Files and Downloading them Using SaveAs Dialog

I have the following code to zip all the files and then save it to the harddisk. I want zip all the files (this is done) and then attach the zip file to the Response stream so that the user have the option to save it!
protected void DownloadSelectedFiles_Click(object sender, EventArgs e)
{
string path = String.Empty;
string zipFilePath = #"C:\MyZipFile.zip";
ZipOutputStream zipStream = new ZipOutputStream(File.Create(zipFilePath));
byte[] buffer = new byte[4096];
foreach (GridViewRow row in gvFiles.Rows)
{
bool isSelected = (row.FindControl("chkSelect") as CheckBox).Checked;
if (isSelected)
{
path = (row.FindControl("lblUrl") as Label).Text;
ZipEntry entry = new ZipEntry(Path.GetFileName(path));
entry.DateTime = DateTime.Now;
zipStream.PutNextEntry(entry);
using (FileStream fs = File.OpenRead(path))
{
int sourceBytes;
do
{
sourceBytes = fs.Read(buffer, 0, buffer.Length);
zipStream.Write(buffer, 0, sourceBytes);
} while (sourceBytes > 0);
}
}
}
zipStream.Finish();
zipStream.Close();
Response.ContentType = "application/x-zip-compressed";
Response.AppendHeader("Content-Disposition", "attachment; filename=SS.zip");
Response.WriteFile(zipFilePath);
Response.End();
}
I blogged about sending files like this a while ago. You might find something usefull in there.
http://absolutecobblers.blogspot.com/2008/02/downloading-and-deleting-temporary.html
If you are using IE, check that its not the old "cache is full"-bug that is showing its ugly face.
And if you have IE set to refresh cashe Automatically or on IE-start and have downloaded that zip-file broken the first time, then it could be that it uses the cached version of that zip-file after you fixed your routine and got a good zip.
Try to add:
Response.Buffer = true;
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
before your Response.ContentType
and add this:
Response.Flush()
Response.Close()
before response.end, and see if that changes anything.
So the result is this:
Response.Buffer = true;
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/x-zip-compressed";
Response.AppendHeader("Content-Disposition", "attachment; filename=SS.zip");
Response.WriteFile(zipFilePath);
Response.Flush()
Response.Close()
Response.End();
Just some tips just from the top of the mind.
I also tried to save the zip file to the server folder and then giving a link to the user to download it but it says the same "The file is corrupted". This is very strange since I can open the same folder if I visit my server folder and manually open it!
Here is another thing I found. If I save the zip file in the Server's folder and then reference it using the url: http://localhost/MyApplication/ServerFolder/MyZipFile.zip.
If I go to the url and download the zip file I get the same error "File is corrupted". But if I manually go to the folder using file explorer and open the file then it works as expected.
Why and How?
And a long shot, try set the mime type to application/unknown, in this post there seems to be part of the solution to the posters problem:
http://jamesewelch.com/2008/12/03/sharpziplib-and-windows-extraction-wizard-errors/

Resources