I have a SaveFileDialog to save file from database.
It works fine until I host the website on IIS. Then it starts to open debugger.
Apparently the dialog gets blocked but I don't have further ideas on what I can use instead.
My code is.
SaveFileDialog save = new SaveFileDialog();
save.FileName = tbl.Rows[0][0].ToString();
if (save.ShowDialog() == DialogResult.OK && save.FileName != "")
{
FileStream FS1 = new FileStream(save.FileName, FileMode.Create);
byte[] blob = (byte[])tbl.Rows[0][1];
FS1.Write(blob, 0, blob.Length);
FS1.Close();
FS1 = null;
}
Any help would be appreciated.
I guess you are using a Windows Forms SaveFileDialog in an ASP.NET website. This is not possible. Maybe it works on you development machine since the Cassini service is running as current user.
Solution:
Write something that works for ASP.NET
String FileName = tbl.Rows[0][0].ToString();
String FilePath = "C:/...."; //Replace this
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
byte[] blob = File.ReadAllBytes(FilePath );
response.BinaryWrite(blob );
response.Flush();
response.End();
There is HttpContext.Current.Response.Write and HttpContext.Current.Response.BinaryWrite and client browser should handle how to save it
using System;
using System.IO;
using System.Web.UI;
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
// 1.
// Get path of byte file.
string path = Server.MapPath("~/Adobe2.png");
// 2.
// Get byte array of file.
byte[] byteArray = File.ReadAllBytes(path);
// 3A.
// Write byte array with BinaryWrite.
Response.BinaryWrite(byteArray);
// 3B.
// Write with OutputStream.Write [commented out]
// Response.OutputStream.Write(byteArray, 0, byteArray.Length);
// 4.
// Set content type.
Response.ContentType = "image/png";
}
}
example from http://www.dotnetperls.com/response-binarywrite
Related
I'm debugging a rather odd situation involving DotNetZip and ASP.NET. Long story short, the resulting zip files that are being created by the code are being reliably downloaded by Firefox, but most other browsers are intermittently returning a Network Error. I've examined the code and it reads about as generically as anything that involves DotNetZip.
Any clues?
Thanks!
EDIT: Here's the complete method. As I mentioned, it's about as generic as it gets:
protected void btnDownloadFolders_Click(object sender, EventArgs e)
{
//Current File path
var diRoot = new DirectoryInfo(_currentDirectoryPath);
var allFiles = Directory.GetFiles(diRoot.FullName, "*.*", SearchOption.AllDirectories);
Response.Clear();
Response.BufferOutput = false;
var archiveName = String.Format("{0}-{1}.zip", diRoot.Name, DateTime.Now.ToString("yyyy-MM-dd HHmmss"));
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "inline; filename=\"" + archiveName + "\"");
using (var zip = new ZipFile())
{
foreach (var strFile in allFiles)
{
var strFileName = Path.GetFileName(strFile);
zip.AddFile(strFile,
strFile.Replace("\\" + strFileName, string.Empty).Replace(diRoot.FullName, string.Empty));
}
zip.Save(Response.OutputStream);
}
Response.Close();
}
It could be because you are not sending the content-length. I've seen errors occur in sending files to the browser where it was not specified. So create the zip file in a MemoryStream. save the stream to a Byte Array so you can send the length as a Response also. Although I can't say for sure that it will fix your specific problem.
byte[] bin;
using (MemoryStream ms = new MemoryStream())
{
using (var zip = new ZipFile())
{
foreach (var strFile in allFiles)
{
var strFileName = Path.GetFileName(strFile);
zip.AddFile(strFile, strFile.Replace("\\" + strFileName, string.Empty).Replace(diRoot.FullName, string.Empty));
}
//save the zip into the memorystream
zip.Save(ms);
}
//save the stream into the byte array
bin = ms.ToArray();
}
//clear the buffer stream
Response.ClearHeaders();
Response.Clear();
Response.Buffer = true;
//set the correct contenttype
Response.ContentType = "application/zip";
//set the filename for the zip file package
Response.AddHeader("content-disposition", "attachment; filename=\"" + archiveName + "\"");
//set the correct length of the data being send
Response.AddHeader("content-length", bin.Length.ToString());
//send the byte array to the browser
Response.OutputStream.Write(bin, 0, bin.Length);
//cleanup
Response.Flush();
HttpContext.Current.ApplicationInstance.CompleteRequest();
I've been searching around the internet, but couldn't find any useful answer.
I have an ASP.NET web site, which is deployed on server.
The ASP.NET web site on the server can access a directory called W:/ .
The clients in the company can access the web site. The web site lists in a ListBox all the PDF files from the W:/ directory. The client should be able to select PDF files from the listbox and save them to it's local PC by selecting a location for it.
Something like save as file on web pages.
Could you provide me some solution or work around ?
Finally I've found an article, which Prompts a Save Dialog Box to Download a File from ASP.NET
I post it here, might help somebody else as well and save some time.
String FileName = "FileName.txt";
String FilePath = "C:/...."; //Replace this
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath);
response.Flush();
response.End();
This is an extension to user1734609's solution that gets a file locally.
To download a file from the server to client:
public void DownloadFile()
{
String FileName = "201604112318571964-sample2.txt";
String FilePath = AppDomain.CurrentDomain.BaseDirectory + "/App_Data/Uploads/" + FileName;
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath);
response.Flush();
response.End();
}
The correct keywords are "File Browser asp.net" to find a lot of examples with source code.
Here is one from codeproject:
http://www.codeproject.com/Articles/301328/ASP-NETUser-Control-File-Browser
Get file contents in byte[] from W drive and write it to local file.
byte[] data = File.ReadAllBytes(WDriveFilePath)
FileStream file = File.Create(HttpContext.Current.Server.MapPath(MyLocalFile));
file.Write(data, 0, data.Length);
file.Close();
I have done something like this to get the file .
protected void btnExportFile_Click(object sender, EventArgs e)
{
try
{
Thread newThread = new Thread(new ThreadStart(ThreadMethod));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
// try using threads as you will get a Current thread must be set to single thread apartment (STA) mode before OLE Exception .
}
catch (Exception ex)
{
}
}
static void ThreadMethod()
{
Stream myStream;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
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();
}
}
}
I am having some problems with downloading files with the save dialog.
My code executes with no errors but no save dialog shows up. Not in FF, not in chrome and not in IE. The attachment can have the following extensions: .jpg,.jpeg,.png,.bmp,.pdf,.txt,.docx. That's why I use Response.ContentType = "application/octet-stream"; (see in code below).
protected void btnDownload_OnCommand(object sender, CommandEventArgs e)
{
//Get the attachment to download from the webservice
RCX.AddressAttachment attachment = ShopClient.GetAddressAttachment(ServiceContext,
new AddressAttachmentCriteria()
{
Id = (string) e.CommandArgument //= AttachmentID
});
//Get a random filename
var fileName = string.Format("{0}{1}", Guid.NewGuid(), attachment.FileExtension);
//Get the physicalPath to save the file
var physicalPath = string.Format(#"{0}\Attachments\{1}", System.AppDomain.CurrentDomain.BaseDirectory,
fileName);
//Get the webpath to navigate to the file
var webPath = string.Format("{0}Attachments/{1}", Misc.BaseUrl(Request.Url), fileName);
//Create file if not exists
using (new FileStream(physicalPath, FileMode.OpenOrCreate))
{
}
//Write bytes to file
System.IO.File.WriteAllBytes(physicalPath, attachment.Attachment);
var fileInfo = new FileInfo(physicalPath);
//Try to open the save dialog, what is wrong here?
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0};", fileName));
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.WriteFile(physicalPath);
Response.End();
}
The file exists after executing the WriteAllBytes(string path, byte[] bytearray) method.
If I navigate to the webPath in my code, I can also see the file in the browser (see code below).
Response.Redirect(webPath);
What could I be doing wrong?
Many thanks.
Try this
Response.Flush();
before the Response.End();
I've been searching around the internet, but couldn't find any useful answer.
I have an ASP.NET web site, which is deployed on server.
The ASP.NET web site on the server can access a directory called W:/ .
The clients in the company can access the web site. The web site lists in a ListBox all the PDF files from the W:/ directory. The client should be able to select PDF files from the listbox and save them to it's local PC by selecting a location for it.
Something like save as file on web pages.
Could you provide me some solution or work around ?
Finally I've found an article, which Prompts a Save Dialog Box to Download a File from ASP.NET
I post it here, might help somebody else as well and save some time.
String FileName = "FileName.txt";
String FilePath = "C:/...."; //Replace this
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath);
response.Flush();
response.End();
This is an extension to user1734609's solution that gets a file locally.
To download a file from the server to client:
public void DownloadFile()
{
String FileName = "201604112318571964-sample2.txt";
String FilePath = AppDomain.CurrentDomain.BaseDirectory + "/App_Data/Uploads/" + FileName;
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition", "attachment; filename=" + FileName + ";");
response.TransmitFile(FilePath);
response.Flush();
response.End();
}
The correct keywords are "File Browser asp.net" to find a lot of examples with source code.
Here is one from codeproject:
http://www.codeproject.com/Articles/301328/ASP-NETUser-Control-File-Browser
Get file contents in byte[] from W drive and write it to local file.
byte[] data = File.ReadAllBytes(WDriveFilePath)
FileStream file = File.Create(HttpContext.Current.Server.MapPath(MyLocalFile));
file.Write(data, 0, data.Length);
file.Close();
I have done something like this to get the file .
protected void btnExportFile_Click(object sender, EventArgs e)
{
try
{
Thread newThread = new Thread(new ThreadStart(ThreadMethod));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
// try using threads as you will get a Current thread must be set to single thread apartment (STA) mode before OLE Exception .
}
catch (Exception ex)
{
}
}
static void ThreadMethod()
{
Stream myStream;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
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();
}
}
}
When I try to generate an Excel file using EPPlus, Excel give me the following error message:
Excel cannot open the file 'myfilename.xlsx' because the file format or file extension is not valid. Verify the the file has not been corrupted and that the file extension matches the format of the file.
Here's my code:
public ActionResult Index()
{
using (ExcelPackage package = new ExcelPackage())
{
// I populate the worksheet here. I'm 90% sure this is fine
// because the stream file size changes based on what I pass to it.
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
var cd = new System.Net.Mime.ContentDisposition
{
Inline = false,
FileName = fileName
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(stream, contentType, fileName);
}
}
Any idea what I'm doing wrong?
All you need to do is reset the stream position. stream.Position = 0;
You shouldn't write directly to the Response, it's not the MVC way. It doesn't follow the correct MVC pipeline and it tightly couples your controller action code to the Response object.
When you add a file name as the 3rd parameter in File(), MVC automatically adds the correct Content-Disposition header... so you shouldn't need to add it manually.
The short of it is, this is what you want:
public ActionResult Index()
{
using (ExcelPackage package = new ExcelPackage())
{
// I populate the worksheet here. I'm 90% sure this is fine
// because the stream file size changes based on what I pass to it.
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
return File(stream, contentType, fileName);
}
}
Your code doesn't show stream being written to the HttpResponse - presumably being done in the File method which you haven't posted.
One way that does work is the following:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader(
"content-disposition", String.Format(CultureInfo.InvariantCulture, "attachment; filename={0}", fileName));
Response.BinaryWrite(package.GetAsByteArray());
Response.End();
Similar to Joe's answer, I still had to call Response.ClearHeaders():
protected void btnDownload_Click(object sender, EventArgs e)
{
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample2");
ws.Cells["A1"].Value = "Sample 2";
ws.Cells["A1"].Style.Font.Bold = true;
var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect);
shape.SetPosition(50, 200);
shape.SetSize(200, 100);
shape.Text = "Sample 2 outputs the sheet using the Response.BinaryWrite method";
Response.Clear();
Response.ClearHeaders();
Response.BinaryWrite(pck.GetAsByteArray());
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Sample2.xlsx");
Response.End();
}