What is my issue here? When I write the stream back out to web, open the file it contains some of the content but all malformed and some missing.
Am I experiencing loss of data due to a logic error?
Note: the readstream and writestream below mocks up what a service will be filling in. I will be receiving a stream to read from the service. I'll need to write that stream back out.
MemoryStream writeStream = new MemoryStream();
byte[] buffer = new byte[256];
OrderDocument doc = new OrderDocument();
doc.Format = "xml";
doc.DocumentId = "5555555";
doc.Aid = "ZZ";
doc.PrimaryServerPort = "PORT";
MemoryStream readStream = new MemoryStream(doc.GetDocument());
while (readStream != null && readStream.Read(buffer, 0, buffer.Length) > 0)
{
writeStream.Write(buffer, 0, buffer.Length);
}
writeStream.Flush();
writeStream.Position = 0;
Response.Buffer = true;
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "text/xml";
Response.ClearHeaders();
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xml", doc.DocumentId));
Response.AddHeader("Content-Length", writeStream.Length.ToString());
Response.BinaryWrite(writeStream.ToArray());
Response.End();
Am I experiencing loss of data due to a logic error?
Yes probably, you may try simplifying your code a little bit. I don't really see the need of multiple memory streams here:
OrderDocument doc = new OrderDocument();
doc.Format = "xml";
doc.DocumentId = "5555555";
doc.Aid = "ZZ";
doc.PrimaryServerPort = "PORT";
byte[] buffer = doc.GetDocument();
Response.Buffer = true;
Response.Clear();
Response.ClearHeaders();
Response.ContentType = "text/xml";
Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xml", doc.DocumentId));
Response.OutputStream.Write(buffer, 0, buffer.Length);
Related
I can generate the Pdf but I want to save the pdf in folder before show to the view.
I have read many articles but I did not find any proper solution.
Here is my code.
ReportDocument rd = new CrystalDecisions.CrystalReports.Engine.ReportDocument();
rd.Load(Path.Combine(Server.MapPath("~/Reports"), "BillInformationReport.rpt"));
rd.SetDataSource(ds);
Stream stream = rd.ExportToStream(ExportFormatType.PortableDocFormat);
MemoryStream ms = new MemoryStream();
stream.CopyTo(ms);
Byte[] fileBuffer = ms.ToArray();
Response.Buffer = false;
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AddHeader("content-length", fileBuffer.Length.ToString());
Response.BinaryWrite(fileBuffer);
rd.Close();
rd.Dispose();
return null;
I am trying to write a file to the output response stream using ASP.Net. When I download the file, I get a Errors were found opening .zip file. You can extract files from this archive, but other programs may not be able to open it. Do you want to try fixing the problems? error. I am however able to cancel this and open the zip file correctly.
What could I be doing wrong?
ASP.Net\C# code:
var pathToFile = "c:\abc.zip";
string fileName = Path.GetFileName(pathToFile);
byte[] buffer;
using (var fileStream = new FileStream(pathToFile, Filemode.open))
{
buffer = new byte[fileStream. Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
}
Response.Clear();
Response.Buffer = true;
Response.AppendHeader("content-disposition", string.Format(#"attachment; filename={0}.zip", filename));
Response.ContentType = "application/zip";
Response.AppendHeader("content-length", buffer.Length.ToString());
Response.WriteFile(pathToFile);
If you want to use buffer and write file to user, do not use Response.WriteFile.
Change to Response.OutputStream.Write, and modify your codes, like this:
var pathToFile = "c:\abc.zip";
string fileName = Path.GetFileName(pathToFile);
byte[] buffer = new byte[0];
using (var fileStream = new FileStream(pathToFile, FileMode.Open, FileAccess.Read))
{
buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, buffer.Length);
}
Response.Clear();
Response.AppendHeader("content-disposition", string.Format(#"attachment; filename={0}", filename));
Response.ContentType = "application/zip";
Response.OutputStream.Write(buffer, 0, buffer.Length);
Response.Flush();
Response.End();
I'm using a 3rd party html to pdf conversion (DocRaptor). You POST your HTML to their site and they respond with the PDF. The starter code they give you works fine, but it puts the file to your harddrive. I modified their code to get it to come through the browser and as a file download. So I'm 100% confident the data I'm getting from the HTTP response is good data. I can't seem to assemble it back to a useable file.
I'm reasonably confident the issue is how I'm handing the responseStream data. It all seems to go wrong once I enter the Try/Catch. I'm very new to c# and web programming, so I would very much appreciate some guidance from the SO users here. Thanks. Here is my code.
string postData = String.Format(PostFormat,
(string.IsNullOrEmpty(DocumentContent) ? "document_url" : "document_content"),
HttpUtility.UrlEncode(string.IsNullOrEmpty(DocumentContent) ? DocumentURL : DocumentContent),
HttpUtility.UrlEncode(Name),
HttpUtility.UrlEncode(type),
HttpUtility.UrlEncode(Test.ToString().ToLower()),
HttpUtility.UrlEncode(Strict),
HttpUtility.UrlEncode(PrinceOptions));
var byteArray = Encoding.UTF8.GetBytes(postData);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(DocRaptorUrl);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
using (var dataStream = request.GetRequestStream()) { dataStream.Write(byteArray, 0, byteArray.Length); }
System.IO.Stream stream = null;
try
{
using (HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse())
{
using (System.IO.Stream responseStream = httpResponse.GetResponseStream())
{
var filepath = #"C:\Users\David\Downloads\UberwriterUSRReport.pdf";
HttpContext.Current.Response.ContentType = "application/pdf";
// let the browser know how to open the PDF document, attachment or inline, and the file name
HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("attachment; filename=UberwriterUSRReport.pdf"));
stream = new System.IO.FileStream(filepath, System.IO.FileMode.Create);
CopyStream(responseStream, stream);
long bytestToRead = stream.Length;
while (bytestToRead > 0)
{
if (HttpContext.Current.Response.IsClientConnected)
{
byte[] buffer = new Byte[10000];
int length = stream.Read(buffer, 0, 10000);
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
HttpContext.Current.Response.Flush();
bytestToRead = bytestToRead - length;
}
else
{
bytestToRead = -1;
}
}
}
}
}
Is it your intention to save the file to the hardrive before sending it to the browser? Cause that is what you're (incorrectly) doing now.
Best is to enclose the write action in a using statement, cause I don't see you close the stream anywhere:
stream = new System.IO.FileStream(filepath, System.IO.FileMode.Create);
Here you're saving to the file:
CopyStream(responseStream, stream);
Next, you're trying to read your outputstream (with which you just saved the file), to write that to your Response.Outputstream. And you have allready a copystream implementation, so why do it manually here? :
HttpContext.Current.Response.OutputStream.Write(buffer, 0, length);
So, I would say it should be something like:
using (HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse())
{
using (System.IO.Stream responseStream = httpResponse.GetResponseStream())
{
var filepath = #"C:\Users\David\Downloads\UberwriterUSRReport.pdf";
HttpContext.Current.Response.ContentType = "application/pdf";
// let the browser know how to open the PDF document, attachment or inline, and the file name
HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("attachment; filename=UberwriterUSRReport.pdf"));
using (var stream = new System.IO.FileStream(filepath, System.IO.FileMode.Create)) {
CopyStream(responseStream, stream);
}
using (var readstream = new System.IO.FileStream(filepath, System.IO.FileMode.Read)) {
CopyStream(readstream, HttpContext.Current.Response.OutputStream);
}
}
}
Or, if you don't want to save the file on the server at all:
using (HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse())
{
using (System.IO.Stream responseStream = httpResponse.GetResponseStream())
{
// let the browser know how to open the PDF document, attachment or inline, and the file name
HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("attachment; filename=UberwriterUSRReport.pdf"));
CopyStream(responseStream, HttpContext.Current.Response.OutputStream);
}
}
MUCHO thanks much to Stephen for putting me on the right path. I further refined the implementation. I had more code that what was required. All I want is the user to hit a button, post the HTML to the DocRaptor.com site, have them respond with the generated PDF, and that file to appear as a download in the browser. Here is the final implemented code as tested on Azure.
try
{
using (HttpWebResponse httpResponse = (HttpWebResponse)request.GetResponse())
{
using (System.IO.Stream responseStream = httpResponse.GetResponseStream())
{
//var filepath = #"C:\Users\David\Downloads\UberwriterUSRReport.pdf";
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ContentType = "application/pdf";
HttpContext.Current.Response.AddHeader("Content-Disposition", String.Format("atachment; filename=UberwriterUSRReport.pdf"));
HttpContext.Current.Response.BufferOutput = true;
CopyStream(responseStream, HttpContext.Current.Response.OutputStream);
}
}
}
I am trying to use SharpZipLib to generate zip file and let the client download it.
Currently zip folder is created and available on client machine but the issue is download.zip folder is blank. The files which are specified in a folder are not available in zip folder.
Below is the code I tried.
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
ICSharpCode.SharpZipLib.Checksums.Crc32 crc = new ICSharpCode.SharpZipLib.Checksums.Crc32();
//stream directly to client.
ICSharpCode.SharpZipLib.Zip.ZipOutputStream output = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(response.OutputStream);
output.SetLevel(9);
string[] files = Directory.GetFiles("D:/newfolder/");
for (int i = 0; i < files.Length; i++)
{
ICSharpCode.SharpZipLib.Zip.ZipEntry entry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(files[i].ToString());
entry.DateTime = DateTime.Now;
System.IO.FileStream fs = new System.IO.FileStream(files[i].ToString(), FileMode.Open);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
entry.Size = fs.Length;
fs.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
output.PutNextEntry(entry);
output.Write(buffer, 0, buffer.Length);
}
output.Finish();
output.Close();
response.Clear();
response.ContentType = "D:/Work Area/";
response.AddHeader("Content-Disposition", "attachment; filename=" + "download.zip");
response.End();
Can anyone tell me whats the issue? Why the files are not available in .zip
After browsing the SharpDevelop wiki I found the following which may be of assistance to you in helping you resolve the problem:
using ICSharpCode.SharpZipLib.Zip;
// This will accumulate each of the files named in the fileList into a zip file,
// and stream it to the browser.
// This approach writes directly to the Response OutputStream.
// The browser starts to receive data immediately which should avoid timeout problems.
// This also avoids an intermediate memorystream, saving memory on large files.
//
private void DownloadZipToBrowser(List <string> zipFileList)
{
Response.ContentType = "application/zip";
// If the browser is receiving a mangled zipfile, IIS Compression may cause this problem. Some members have found that
// Response.ContentType = "application/octet-stream" has solved this. May be specific to Internet Explorer.
Response.AppendHeader("content-disposition", "attachment; filename=\"Download.zip\"");
response.CacheControl = "Private";
response.Cache.SetExpires(DateTime.Now.AddMinutes(3)); // or put a timestamp in the filename in the content-disposition
byte[] buffer = new byte[4096];
ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream);
zipOutputStream.SetLevel(3); //0-9, 9 being the highest level of compression
foreach (string fileName in zipFileList) {
Stream fs = File.OpenRead(fileName); // or any suitable inputstream
ZipEntry entry = new ZipEntry(ZipEntry.CleanName(fileName));
entry.Size = fs.Length;
// Setting the Size provides WinXP built-in extractor compatibility,
// but if not available, you can set zipOutputStream.UseZip64 = UseZip64.Off instead.
zipOutputStream.PutNextEntry(entry);
int count = fs.Read(buffer, 0, buffer.Length);
while (count > 0) {
zipOutputStream.Write(buffer, 0, count);
count = fs.Read(buffer, 0, buffer.Length);
if (!Response.IsClientConnected) {
break;
}
Response.Flush();
}
fs.Close();
}
zipOutputStream.Close();
Response.Flush();
Response.End();
}
CRC32 corresponds to each compressed file.
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
//stream directly to client.
ICSharpCode.SharpZipLib.Zip.ZipOutputStream output = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(response.OutputStream);
output.SetLevel(9);
string[] files = Directory.GetFiles("D:/newfolder/");
for (int i = 0; i < files.Length; i++)
{
ICSharpCode.SharpZipLib.Checksums.Crc32 crc = new ICSharpCode.SharpZipLib.Checksums.Crc32();
ICSharpCode.SharpZipLib.Zip.ZipEntry entry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(files[i].ToString());
entry.DateTime = DateTime.Now;
System.IO.FileStream fs = new System.IO.FileStream(files[i].ToString(), FileMode.Open);
byte[] buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);
entry.Size = fs.Length;
fs.Close();
crc.Reset();
crc.Update(buffer);
entry.Crc = crc.Value;
output.PutNextEntry(entry);
output.Write(buffer, 0, buffer.Length);
}
output.Finish();
output.Close();
response.Clear();
response.ContentType = "D:/Work Area/";
response.AddHeader("Content-Disposition", "attachment; filename=" + "download.zip");
response.End();
I don't understand what is missing here. I am trying to export a file in csv format with extended ASCII characters like ÿ or ü but all i get is �
Do I need to specify something else in the response?
Encoding encoding = Encoding.UTF8;
//ToCSV writes the string correctly
var bytes = encoding.GetBytes("write ÿ or ü please");
MemoryStream stream = new MemoryStream(bytes);
StreamReader reader = new StreamReader(stream);
//TextWriter tw = new TextWriter();
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", string.Format("attachment;filename={0}.csv", fileName));
Response.Charset = encoding.EncodingName;
Response.ContentType = "application/text";
Response.Output.Write(reader.ReadToEnd());
Response.Flush();
Response.End();
I believe you should add Response.ContentEncoding = Encoding.Unicode to get right output.
Encoding encoding = Encoding.UTF8;
var bytes = encoding.GetBytes("write ÿ or ü please");
MemoryStream stream = new MemoryStream(bytes);
StreamReader reader = new StreamReader(stream);
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", string.Format("attachment;filename={0}.csv", "filename"));
Response.Charset = encoding.EncodingName;
Response.ContentType = "application/text";
Response.ContentEncoding = Encoding.Unicode;
Response.Output.Write(reader.ReadToEnd());
Response.Flush();
Response.End();
Unfortunately Encoding.Unicode didn't work, using Windows-1252 worked :
Response.Clear();
Response.ContentType = "Application/x-msexcel";
Response.AddHeader("content-disposition", "attachment; filename=\"filename.csv\"");
Response.ContentEncoding = System.Text.Encoding.GetEncoding("Windows-1252");
Response.Write(string.Join(Environment.NewLine, myDataLines));
Response.End();
I'm a Java programmer, are you sure you need a StreamReader? I guess StreamReader(stream) may decode the bytes in a different charset. And, You've already got the bytes, maybe you could write the bytes to response directly.