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/
Related
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);
I am using iTextSharp for creating pdf reports (files) and storing those on the web server where my application resides. I am able to create the file, go into the storage folder and open the file without a problem. Notice: The user is not to get the file automatically
downloaded on creation.
I want to give the user the option to download "old" reports from the server with a button.
This is working fine in IE (10) but not in Chrome and Firefox. I always get the error message:
There was an error opening this document. The file is damaged and could not be repaired.
I have this image button and on click I send the user to a Generic Handler (since my page contains Update Panels) according to this post (only using it partially for now).
This is the code that actually downloads the file:
public void ProcessRequest(HttpContext context)
{
var _fileName = context.Request.QueryString["fileName"];
using (var _output = new MemoryStream())
{
//var _fileSeverPath = context.Server.MapPath(_fileName);
context.Response.Clear();
context.Response.ContentType = "application/pdf";// "application/pdf";
//context.Response.AppendHeader("Content-Length", _fileName.Length.ToString());
context.Response.AppendHeader("Content-Disposition", string.Format("attachment; filename=" + Path.GetFileName(_fileName)));
context.Response.WriteFile(_fileName);
context.Response.Flush();
context.Response.Close();
context.Response.End();
}
}
As I said, this works fine in IE but not in Chrome and Firefox.
When I open the file in Notepad it seams that I only get about 1/3 of the file when downloaded in Chrome and Firefox.
Any suggestions would be greatly appreciated. Been trying to resolve this for a few days now..
From HttpResponse.WriteFile Method (String)
When this method is used with large files, calling the method might
throw an exception. The size of the file that can be used with this
method depends on the hardware configuration of the Web server. For
more information, see article 812406, "PRB: Response.WriteFile Cannot
Download a Large File" on the Microsoft Knowledge Base Web site.
Try this instead:
public void ProcessRequest(HttpContext context)
{
var _fileName = context.Request.QueryString["fileName"];
context.Response.Clear();
context.Response.Buffer = true;
context.Response.ContentType = "application/pdf";
context.Response.AppendHeader(
"Content-Disposition",
string.Format("attachment; filename=" + Path.GetFileName(_fileName)));
using (var fs = new FileStream(_fileName, FileMode.Open, FileAccess.Read))
{
using (var sr = new StreamReader(fs, true))
{
int length = (int)fs.Length;
byte[] buffer;
using (BinaryReader br = new BinaryReader(fs, sr.CurrentEncoding))
{
buffer = br.ReadBytes(length);
context.Response.BinaryWrite(buffer);
}
}
}
context.Response.Flush();
context.Response.Close();
context.Response.End();
}
Ok, FINALLY.. I found the solution and it makes me feel like a fool at the same time..
Removed context.Response.Close(); ...then everything worked perfectly :)
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();
I implemented a generic handler in my application which works great for images, but when I manually type the handler URL in the browser with the image's querystring it prompts download instead of displaying. Here is my code:
public void ProcessRequest(HttpContext context)
{
if (this.FileName != null)
{
string path = Path.Combine(ConfigurationManager.UploadsDirectory, this.FileName);
if (File.Exists(path) == true)
{
FileStream file = new FileStream(path, FileMode.Open);
byte[] buffer = new byte[(int)file.Length];
file.Read(buffer, 0, (int)file.Length);
file.Close();
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader("content-disposition", "attachment; filename=\"" + this.FileName + "\"");
context.Response.BinaryWrite(buffer);
context.Response.End();
}
}
}
I am using the octet-stream because I'm dealing with more than just images and I don't always know the content type of the file. Thanks in advance!
The only way is to specify correct ContentType so the browser know what to do with receiving file, depending on installed plugins (for example, view pdf files in browser frame) and system assosiations (for example, offer to open document in MS Office instead of simple download)
You can try to specify Content Type depending on file extension, i.e.:
if(Path.GetExtension(path) == ".jpg")
context.Response.ContentType = "image/jpeg";
else
context.Response.ContentType = "application/octet-stream";
If you store the ContentType as part of the files metadata, when you pull it back down your could use it.
theFile = GetFile(id)
context.Response.ContentType = theFile.Type;
The content-disposition header is the one that causes your browser to show the download dialog. Remove that line and it will show in the browser.
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();