Cannot access a disposed object. Object name: System.Net.Sockets.NetworkStream - c#

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.

Related

I need to append multiple filestreams to the same pdf file

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);
}
}

Download URL Content-Disposition excel file using C#

I need to download a file attached to a URL using C# and I have written this piece of code:
var uri = new Uri("http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=0");
var request = WebRequest.CreateHttp(uri);
var response = request.GetResponse();
string disposition = response.Headers["Content-Disposition"];
string filename = disposition.Substring(disposition.IndexOf("filename=") + 9).Replace("\"", "");
using (var fs = new FileStream(filename.Replace("/", "-"), FileMode.Create, FileAccess.Write, FileShare.None))
{
response.GetResponseStream().CopyTo(fs);
}
But the excel file saved in the path seems to be corrupted
I get a forbidden back when trying to call your URL. In my example I have used a different URL which is working fine.
var request = WebRequest.CreateHttp("http://spreadsheetpage.com/downloads/xl/king-james-bible.xlsm");
var response = request.GetResponse();
using (var fs = new FileStream("king-james-bible.xlsm", FileMode.Create, FileAccess.Write, FileShare.None))
{
using (var stream = response.GetResponseStream())
{
stream.CopyTo(fs);
}
}
Could it be that the file your retrieving itself is corrupt?
Updated based on the new information
Okay the link is now working for me. Your problem is that the Excel file is sent using a gzip encoding. The code sample below works with your URL.
var request = WebRequest.CreateHttp("http://members.tsetmc.com/tsev2/excel/MarketWatchPlus.aspx?d=0");//"http://spreadsheetpage.com/downloads/xl/king-james-bible.xlsm");
var response = request.GetResponse();
string disposition = response.Headers["Content-Disposition"];
string filename = disposition.Substring(disposition.IndexOf("filename=") + 9).Replace("\"", "");
using (var fs = new FileStream(filename.Replace("/", "-"), FileMode.Create, FileAccess.Write, FileShare.None))
{
using (var stream = response.GetResponseStream())
{
using (GZipStream zipStream = new GZipStream(stream, CompressionMode.Decompress))
{
byte[] tempBytes = new byte[4096];
int i;
while ((i = zipStream.Read(tempBytes, 0, tempBytes.Length)) != 0)
{
fs.Write(tempBytes, 0, i);
}
}
}
}
I have used the info from this post for the gzip decoding: How do you download and extract a gzipped file with C#?

Read the content of an xml file within a zip package

I am required to read the contents of an .xml file using the Stream (Here the xml file is existing with in the zip package). Here in the below code, I need to get the file path at runtime (here I have hardcoded the path for reference). Please let me know how to read the file path at run time.
I have tried to use string s =entry.FullName.ToString(); but get the error "Could not find the Path". I have also tried to hard code the path as shown below. however get the same FileNotFound error.
string metaDataContents;
using (var zipStream = new FileStream(#"C:\OB10LinuxShare\TEST1\Temp" + "\\"+zipFileName+".zip", FileMode.Open))
using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Read))
{
foreach (var entry in archive.Entries)
{
if (entry.Name.EndsWith(".xml"))
{
FileInfo metadataFileInfo = new FileInfo(entry.Name);
string metadataFileName = metadataFileInfo.Name.Replace(metadataFileInfo.Extension, String.Empty);
if (String.Compare(zipFileName, metadataFileName, true) == 0)
{
using (var stream = entry.Open())
using (var reader = new StreamReader(stream))
{
metaDataContents = reader.ReadToEnd();
clientProcessLogWriter.WriteToLog(LogWriter.LogLevel.DEBUG, "metaDataContents : " + metaDataContents);
}
}
}
}
}
I have also tried to get the contents of the .xml file using the Stream object as shown below. But here I get the error "Stream was not readable".
Stream metaDataStream = null;
string metaDataContent = string.Empty;
using (Stream stream = entry.Open())
{
metaDataStream = stream;
}
using (var reader = new StreamReader(metaDataStream))
{
metaDataContent = reader.ReadToEnd();
}
Kindly suggest, how to read the contents of the xml with in a zip file using Stream and StreamReader by specifying the file path at run time
Your section code snippet is failing because when you reach the end of the first using statement:
using (Stream stream = entry.Open())
{
metaDataStream = stream;
}
... the stream will be disposed. That's the point of a using statment. You should be fine with this sort of code, but load the XML file while the stream is open:
XDocument doc;
using (Stream stream = entry.Open())
{
doc = XDocument.Load(stream);
}
That's to load it as XML... if you really just want the text, you could use:
string text;
using (Stream stream = entry.Open())
{
using (StreamReader reader = new StreamReader(stream))
{
text = reader.ReadToEnd();
}
}
Again, note how this is reading before it hits the end of either using statement.
Here is a sample of how to read a zip file using .net 4.5
private void readZipFile(String filePath)
{
String fileContents = "";
try
{
if (System.IO.File.Exists(filePath))
{
System.IO.Compression.ZipArchive apcZipFile = System.IO.Compression.ZipFile.Open(filePath, System.IO.Compression.ZipArchiveMode.Read);
foreach (System.IO.Compression.ZipArchiveEntry entry in apcZipFile.Entries)
{
if (entry.Name.ToUpper().EndsWith(".XML"))
{
System.IO.Compression.ZipArchiveEntry zipEntry = apcZipFile.GetEntry(entry.Name);
using (System.IO.StreamReader sr = new System.IO.StreamReader(zipEntry.Open()))
{
//read the contents into a string
fileContents = sr.ReadToEnd();
}
}
}
}
}
catch (Exception)
{
throw;
}
}

Read webpage - avoid diamond / question mark for non-standard chars

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();
}
}
}

To download a zipped file from FTP

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;
}

Categories