I have a function that converts a ZPL(Zebra Label) into a PDF format and saves the file. What I'm trying to do is instead of overwriting the file each time, I would like to append the filestream to the file (if it exists), write new (if not exists).
I've tried setting a new filestream with filemode.append, that did not seem to make a difference.
private static void SaveLabel(string label, string labelDir, string caseNumber)
{
var zpl = Encoding.UTF8.GetBytes(label);
var fileName = $#"{labelDir}\{caseNumber}.pdf";
// adjust print density (8dpm), label width (4 inches), label height (6 inches), and label index (0) as necessary
var request = (HttpWebRequest)WebRequest.Create("http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/");
request.Method = "POST";
request.Accept = "application/pdf"; // omit this line to get PNG images back
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = zpl.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(zpl, 0, zpl.Length);
requestStream.Close();
try
{
var response = (HttpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
if (!File.Exists(fileName))
File.Create(fileName);
using (var fileStream = File.Open(fileName, FileMode.Append))
{
responseStream?.CopyTo(fileStream);
responseStream?.Close();
fileStream.Close();
}
}
catch (WebException e)
{
Console.WriteLine(#"Error: {0}", e.Status);
}
}
I first check to see if the file existed (meaning there was going to be more than one label for the shipment). If not, process as normal. If yes, then read that file into a new pdf file. Then read the contents of the current response stream into a 2nd new pdf file.
I then delete the destination file freeing the name for the new combined pdf. I then use the suggested link to PDFSharp and combine the pages and save as the original file name. This will enable a continuous appending of the file regardless of how many package labels are generated.
private static void SaveLabel(string label, string labelDir, string caseNumber)
{
var zpl = Encoding.UTF8.GetBytes(label);
var destFileName = $#"{labelDir}\{caseNumber}.pdf";
// adjust print density (8dpm), label width (4 inches), label height (6 inches), and label index (0) as necessary
var request = (HttpWebRequest)WebRequest.Create("http://api.labelary.com/v1/printers/8dpmm/labels/4x6/0/");
request.Method = "POST";
request.Accept = "application/pdf"; // omit this line to get PNG images back
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = zpl.Length;
var requestStream = request.GetRequestStream();
requestStream.Write(zpl, 0, zpl.Length);
requestStream.Close();
try
{
var response = (HttpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
if (File.Exists(destFileName))
{
var oldStream = File.OpenRead(destFileName);
var oldFileName = $#"{labelDir}\{caseNumber}-1.pdf";
using (var fileStream = File.Open(oldFileName, FileMode.Create))
{
oldStream.CopyTo(fileStream);
oldStream.Close();
fileStream.Close();
}
var newFileName = $#"{labelDir}\{caseNumber}-2.pdf";
using (var fileStream = File.Open(newFileName, FileMode.Create))
{
responseStream?.CopyTo(fileStream);
responseStream?.Close();
fileStream.Close();
}
File.Delete(destFileName);
using (var pdfOne = PdfReader.Open(oldFileName, PdfDocumentOpenMode.Import))
{
using (var pdfTwo = PdfReader.Open(newFileName, PdfDocumentOpenMode.Import))
{
using (var outPdf = new PdfDocument())
{
CopyPages(pdfOne, outPdf);
CopyPages(pdfTwo, outPdf);
outPdf.Save(destFileName);
}
}
}
File.Delete(oldFileName);
File.Delete(newFileName);
}
else
{
using (var fileStream = File.Open(destFileName, FileMode.Create))
{
responseStream?.CopyTo(fileStream);
responseStream?.Close();
fileStream.Close();
}
}
}
catch (WebException e)
{
Console.WriteLine(#"Error: {0}", e.Status);
}
}
Related
I am using CsvHelper. Here I am trying to download a csv file from ftp and write to a class. It's throwing an error - Cannot access a disposed object. Object name: System.Net.Sockets.NetworkStream. from line -
IEnumerable records = csv.GetRecords().ToList();
Any idea?
request.Credentials = new NetworkCredential(ftpUser, ftpPwd);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.UseBinary = true;
// Csv file
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (TextReader tr = new StreamReader(responseStream))
{
using (CsvReader csv = new CsvReader(tr))
{
if (csvUpload.IncludeInvoice) csv.Configuration.RegisterClassMap<PacketUploadInvoiceMasterMap>();
else csv.Configuration.RegisterClassMap<PacketUploadBasicMasterMap>();
IEnumerable<PacketUploadMaster> records = csv.GetRecords<PacketUploadMaster>().ToList();
pumResults = records.ToList();
}
}
}
}
response.Close();
}
In order to fix this issue, I had to do File reading and writing in csv separately like below
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (MemoryStream ms = new MemoryStream())
{
responseStream.CopyTo(ms);
streamInByte = ms.ToArray();
}
}
}
using (TextReader tr = new StreamReader(new MemoryStream(streamInByte), Encoding.Default))
{
using (CsvReader csv = new CsvReader(tr))
{
// The value used to escape fields that contain a delimiter, quote, or line ending.
// csv.Configuration.Quote = '"';
if (csvUpload.IncludeInvoice) csv.Configuration.RegisterClassMap<PacketUploadInvoiceMasterMap>();
else csv.Configuration.RegisterClassMap<PacketUploadBasicMasterMap>();
// Remove white space from header
csv.Configuration.TrimHeaders = true;
IEnumerable<PacketUploadMaster> records = csv.GetRecords<PacketUploadMaster>().ToList();
pumResults = records.ToList();
}
}
When the using of responseStream ends, it will close and dispose both the responseStream and its underlying stream which happens to be your FtpWebResponse response. Which is why calling response.Close() will throw Cannot access a disposed object.
I have a C# windows form application which downloads file from a url(asp.net application) but it is not returning full image lets say image is of 780kb the file that windows form creates is 381 bytes exactly.
I am not able to figure out the issue. Please help.
The code i am using for download is:
public bool getFileFromURL(string url, string filename)
{
long contentLength = 0;
Stream stream = null;
try
{
WebRequest req = WebRequest.Create(url);
WebResponse response = req.GetResponse();
stream = response.GetResponseStream();
contentLength = response.ContentLength;
// Transfer the file
byte[] buffer = new byte[10 * 1024]; // 50KB at a time
int numBytesRead = 0;
long totalBytesRead = 0;
using (FileStream fileStream = new FileStream(filename, FileMode.Create))
{
using (BinaryWriter fileWriter = new BinaryWriter(fileStream))
{
while (stream.CanRead)
{
numBytesRead = stream.Read(buffer, 0, buffer.Length);
if (numBytesRead == 0) break;
totalBytesRead += numBytesRead;
fileWriter.Write(buffer, 0, numBytesRead);
}
fileWriter.Close();
}
fileStream.Close();
}
stream.Close();
response.Close();
req.Abort();
return true;
}
catch (Exception)
{
return false;
}
}
This is my asp.net app code:
using (PortalEntities db = new PortalEntities())
{
PortalModel.Command command = db.Commands.SingleOrDefault(c => c.id == id);
var filePath = Server.MapPath("~/Uploads/"+command.arguments);
if (!File.Exists(filePath))
return;
var fileInfo = new System.IO.FileInfo(filePath);
Response.ContentType = "image/jpg";
Response.AddHeader("Content-Disposition", String.Format("attachment;filename=\"{0}\"", filePath));
Response.AddHeader("Content-Length", fileInfo.Length.ToString());
Response.WriteFile(filePath);
Response.End();
}
That's an awful lot of code to write some bytes out to a file from a web response. How about something like this (.NET 4+):
public static bool GetFileFromURL(string url, string filename)
{
try
{
var req = WebRequest.Create(url);
using (Stream output = File.OpenWrite(filename))
using (WebResponse res = req.GetResponse())
using (Stream s = res.GetResponseStream())
s.CopyTo(output);
return true;
}
catch
{
return false;
}
}
You can download image in more elegant way, it was discussed before here Unable to locate FromStream in Image class
And use File.WriteAllBytes Method to save the byte array as a file, more info at
http://msdn.microsoft.com/en-us/library/system.io.file.writeallbytes(v=vs.110).aspx
So all your client code can be replaced with
public void getFileFromURL(string url, string filename)
{
using (var webClient = new WebClient())
{
File.WriteAllBytes(filename,webClient.DownloadData(url));
}
}
Dude, why are you not using WebClient.DownloadFileAsync?
private void DownloadFile(string url, string path)
{
using (var client = new System.Net.WebClient())
{
client.DownloadFileAsync(new Uri(url), path);
}
}
That's pretty much it, but this method can't download over 2GB. But i don't think the image is that big xD.
Hope it helps!
I'm trying to read a webpage that contains a registered trademark symbol in the content, i.e. ®. However, when I use quickwatch and look at sb in the below example, I see a diamond with a question mark instead of ®. The same issue occurs if I serialize sb and display it in another webpage via javascript. Is this just how this char will appear in my quickwatch window, or am I reading/decoding the page incorrectly? The code is as follows:
const int bufSize = 4096;
const int maxBytesToGet = 5000000;
byte[] buf = new byte[bufSize];
StringBuilder sb = new StringBuilder(bufSize);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
while ((bytesToGet = responseStream.Read(buf, 0, buf.Length)) != 0)
{
sb.Append(Encoding.UTF8.GetString(buf, 0, bytesToGet));
if (sb.Length > maxBytesToGet) break;
}
}
}
You're assuming the response is UTF8. You need to look at the response headers to see what the encoding actually is. It's also easier to use a StreamReader instead of Encoding.GetString.
string responseText;
using (var response = (HttpWebResponse)request.GetResponse())
{
using (Stream responseStream = response.GetResponseStream())
{
var encoding = Encoding.GetEncoding(response.CharacterSet);
using(var reader = new StreamReader(responseStream, encoding))
{
responseText = reader.ReadToEnd();
}
}
}
I am trying to do this using C#(Winforms).
The code I am using is giving me a string as an output, but I need to have a zipped file.
I am using the following code
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(
"ftp:SITENAME/FILENAME.zip");
request.Method = WebRequestMethods.Ftp.DownloadFile;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential("", "");
FtpWebResponse response = (FtpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader reader = new StreamReader(responseStream);
//StreamWriter writer = new StreamWriter(responseStream);
MessageBox.Show(reader.ReadtoEnd);
MessageBox.Show("Download Complete, status {0}" + response.StatusCode);
reader.Close();
response.Close();
}
catch (NotSupportedException ne)
{
MessageBox.Show(ne.Message);
}
I have an idea that I have to use Open source library from SharpZipLib to convert this string to a zipped file. But,I cannot find any sample code to show me how to do that.
I would really appreciate if someone can guide me through the process.
Thanks,
Sidhanshu
This might do just that.
using ICSharpCode.SharpZipLib.BZip2;
public static string Unzip(byte[] compressedbytes)
{
string result;
MemoryStream m_msBZip2 = null;
BZip2InputStream m_isBZip2 = null;
m_msBZip2 = new MemoryStream(compressedbytes);
// read final uncompressed string size stored in first 4 bytes
using (BinaryReader reader = new BinaryReader(m_msBZip2, System.Text.Encoding.ASCII))
{
Int32 size = reader.ReadInt32();
m_isBZip2 = new BZip2InputStream(m_msBZip2);
byte[] bytesUncompressed = new byte[size];
m_isBZip2.Read(bytesUncompressed, 0, bytesUncompressed.Length);
m_isBZip2.Close();
m_msBZip2.Close();
result = Encoding.ASCII.GetString(bytesUncompressed, 0, bytesUncompressed.Length);
reader.Close();
}
return result;
}
public static byte[] Zip(string sBuffer)
{
byte[] result;
using (MemoryStream m_msBZip2 = new MemoryStream())
{
Int32 size = sBuffer.Length;
// Prepend the compressed data with the length of the uncompressed data (firs 4 bytes)
using (BinaryWriter writer = new BinaryWriter(m_msBZip2, System.Text.Encoding.ASCII))
{
writer.Write(size);
using (BZip2OutputStream m_osBZip2 = new BZip2OutputStream(m_msBZip2))
{
m_osBZip2.Write(Encoding.ASCII.GetBytes(sBuffer), 0, sBuffer.Length);
m_osBZip2.Close();
}
writer.Close();
result = m_msBZip2.ToArray();
m_msBZip2.Close();
}
}
return result;
}
I'm using the following code to grab a wmv file through a WebResponse. I'm using a thread to call this function:
static void GetPage(object data)
{
// Cast the object to a ThreadInfo
ThreadInfo ti = (ThreadInfo)data;
// Request the URL
WebResponse wr = WebRequest.Create(ti.url).GetResponse();
// Display the value for the Content-Length header
Console.WriteLine(ti.url + ": " + wr.Headers["Content-Length"]);
string toBeSaved = #"C:\Users\Kevin\Downloads\TempFiles" + wr.ResponseUri.PathAndQuery;
StreamWriter streamWriter = new StreamWriter(toBeSaved);
MemoryStream m = new MemoryStream();
Stream receiveStream = wr.GetResponseStream();
using (StreamReader sr = new StreamReader(receiveStream))
{
while (sr.Peek() >= 0)
{
m.WriteByte((byte)sr.Read());
}
streamWriter.Write(sr.ReadToEnd());
sr.Close();
wr.Close();
}
streamWriter.Flush();
streamWriter.Close();
// streamReader.Close();
// Let the parent thread know the process is done
ti.are.Set();
wr.Close();
}
The file seems to download just fine, but Windows Media Viewer cannot open the file properly. Some silly error about not being able to support the file type.
What incredibly easy thing am I missing?
You just need to download it as binary instead of text. Here's a method that should do the trick for you.
public void DownloadFile(string url, string toLocalPath)
{
byte[] result = null;
byte[] buffer = new byte[4097];
WebRequest wr = WebRequest.Create(url);
WebResponse response = wr.GetResponse();
Stream responseStream = response.GetResponseStream;
MemoryStream memoryStream = new MemoryStream();
int count = 0;
do {
count = responseStream.Read(buffer, 0, buffer.Length);
memoryStream.Write(buffer, 0, count);
if (count == 0) {
break;
}
}
while (true);
result = memoryStream.ToArray;
FileStream fs = new FileStream(toLocalPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
fs.Write(result, 0, result.Length);
fs.Close();
memoryStream.Close();
responseStream.Close();
}
I do not understand why you are filling MemoryStream m one byte at a time, but then writing the sr to the file. At that point, I believe the sr is empty, and MemoryStream m is never used.
Below is some code I wrote to do a similar task. It gets a WebResponse in 32K chunks at a time, and dumps it directly to a file.
public void GetStream()
{
// ASSUME: String URL is set to a valid URL.
// ASSUME: String Storage is set to valid filename.
Stream response = WebRequest.Create(URL).GetResponse().GetResponseStream();
using (FileStream fs = File.Create(Storage))
{
Byte[] buffer = new Byte[32*1024];
int read = response.Read(buffer,0,buffer.Length);
while (read > 0)
{
fs.Write(buffer,0,read);
read = response.Read(buffer,0,buffer.Length);
}
}
// NOTE: Various Flush and Close of streams and storage not shown here.
}
You are using a StreamReader and a StreamWriter to transfer your stream, but those classes are for handling text. Your file is binary and chances are that sequences of CR, LF and CR LF may get clobbered when you transfer the data. How NUL characters are handled I have no idea.