C# Simple file uploader fails to output a stream - c#

I'm trying to implement file uploading, directly from IsolatedStorage, in my WP7 app. I'm basing on this excellent example http://gregdoesit.com/2009/10/file-upload-in-silverlight-a-simple-solution/
Code I use to begin the UploadChunk() call chain is:
public void uploadPackage(String packagePath)
{
string[] pathSplit = packagePath.Split('\\');
_fileName = pathSplit[1];
IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream packageFile = isf.OpenFile(packagePath, System.IO.FileMode.Open, FileAccess.Read);
_bytesUploaded = 0;
_bytesTotal = packageFile.Length;
_data = packageFile;
try
{
UploadFileChunk();
}
catch (Exception ex)
{
}
}
And everything seems to work well untill wc_OpenWriteCompleted event occurs. It is implemented like so:
if (e.Error == null)
{
object[] objArr = e.UserState as object[];
byte[] fileContent = objArr[0] as byte[]; // NullReferenceException
int bytesRead = Convert.ToInt32(objArr[1]);
Stream outputStream = e.Result;
outputStream.Write(fileContent, 0, bytesRead);
outputStream.Close();
}
objArr, in the 3rd line fails to be assinged, while e.UserState has a non null value. This causes the NullReferenceException in line 4., objArr is null.
What may cause the problem? I'm really stuck with this one, I would really appreciate any of your help.

Related

Odd file does not exist error

I'm running into an error that I can't catch and it should not be there.
if (System.IO.File.Exists (PathToMyFile))
{
try{
FileStream fs = new FileStream(PathToMyFile, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
br.Close();
fs.Close();
myFile =Convert.ToBase64String (bytes) ;
}
catch{}
}
For some reason , sometimes I get a exception error that the file does not exist when It most definitely is there. The very first "If statement" even says it is there yet when trying to open the file I sometimes get a massive app crash that the catch does not "catch" .
Like I said, it's a random error, most of the time the code is perfect but the odd occasion seems to throw an error that the app stops working .
First thing is to make sure you close the file\stream
So you can call fs.Close() or using
if (File.Exists(pathToMyFile))
{
try
{
using (var fs = new FileStream(pathToMyFile, FileMode.Open, FileAccess.Read))
{
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32) fs.Length);
br.Close();
fs.Close();
myFile = Convert.ToBase64String(bytes);
}
}
catch
{
// Log exception
}
}
Second, if you need to read the file as string, simply use
if (File.Exists(pathToMyFile))
{
try
{
myFile = File.ReadAllText(pathToMyFile);
}
catch
{
// Log exception
}
}

I cant copy files using FileStream

I am trying to read/write files using FileStream. Code is working but After copied files all I get an empty file. String data inside the file is not copied.
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if(saveFileDialog1.ShowDialog()==DialogResult.OK)
{
FileStream streamR = new FileStream(openFileDialog1.FileName, FileMode.Open);
byte[] buffer = new byte[streamR.Length];
streamR.Read(buffer, 0, buffer.Length);
FileStream streamW = new FileStream(saveFileDialog1.FileName,FileMode.Create);
int read_byte = 0;
while ((read_byte = streamR.Read(buffer, 0, buffer.Length)) > 0)
{
streamW.Write(buffer, 0, read_byte);
}
}
}
When using streams, you should use the 'using' command:
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
if(saveFileDialog1.ShowDialog()==DialogResult.OK)
{
using (FileStream streamR = new FileStream(openFileDialog1.FileName, FileMode.Open))
{
using (FileStream streamW = new FileStream(saveFileDialog1.FileName,FileMode.Create))
{
byte[] buffer = new byte[streamR.Length];
int read_byte = 0;
while ((read_byte = streamR.Read(buffer, 0, buffer.Length)) > 0)
{
streamW.Write(buffer, 0, read_byte);
}
}
}
}
}
It will automatically flush, close and dispose the streams for you.
What actually stops your code from working, is the flush() and close() command.
However, it's still recommended to use the 'using' command.
A second way is to wrap everything in a try finally block and dispose the stream in the finally block:
using statement FileStream and / or StreamReader - Visual Studio 2012 Warnings
Anyway, I would suggest reading some more information about streams before continuing.
On the other hand ... if it's just for copying files, it would be simpler to use the Fil.Copy method.
Edit: Also ... loading the original file completely into a byte-array can cause some extra problems when your file is quite large.
The buffer is there to read chunks from the original file and process them.
I just corrected your code to make it work ... but it's far from perfect.
I would do something along these lines:
if (openFileDialog1.ShowDialog() == DialogResult.OK
&& saveFileDialog1.ShowDialog() == DialogResult.OK){
try {
if (File.Exists(saveFileDialog1.FileName)) {
File.Delete(saveFileDialog1.FileName);
}
File.Copy(openFileDialog1.FileName, saveFileDialog1.FileName);
} catch (Exception e){
//handle or throw e
}
}

Extract zip entries to another Zip file

Can anyone tell me why the following code doesnt work? I am using the SharpZipLib API for the Zip streams, latest version DL'ed today from their site. Im attempting to use this logic to merge the contents of one zip file into another, without having to perform IO on the disk, as the intended zip files may contain reserved file names for windows. I have tried this with multiple different source and destination zip files (those that contain reserved names and those that dont). The code does not throw any exception, and if you inspect the buffer prior to each write operation, you can see that it contains real data, yet after the entire operation finishes the size of the target zip file has not changed, and you can explore it to confirm that no new files (the ones the code is supposed to add) have actually been added to the destination file. :(
public static void CopyToZip(string inArchive, string outArchive)
{
ZipOutputStream outStream = null;
ZipInputStream inStream = null;
try
{
outStream = new ZipOutputStream(File.OpenWrite(outArchive));
outStream.IsStreamOwner = false;
inStream = new ZipInputStream(File.OpenRead(inArchive));
ZipEntry currentEntry = inStream.GetNextEntry();
while (currentEntry != null)
{
byte[] buffer = new byte[1024];
ZipEntry newEntry = new ZipEntry(currentEntry.Name);
newEntry.Size = currentEntry.Size;
newEntry.DateTime = currentEntry.DateTime;
outStream.PutNextEntry(newEntry);
int size = 0;
while ((size = inStream.Read(buffer, 0, buffer.Length)) > 0)
{
outStream.Write(buffer, 0, size);
}
outStream.CloseEntry();
currentEntry = inStream.GetNextEntry();
}
outStream.IsStreamOwner = true;
}
catch (Exception e)
{
throw e;
}
finally
{
try { outStream.Close(); }
catch (Exception ignore) { }
try { inStream.Close(); }
catch (Exception ignore) { }
}
}
I ended up doing this using a different API. DotNet zip from http://dotnetzip.codeplex.com/. Here is the implementation:
public static void CopyToZip(string inArchive, string outArchive, string tempPath)
{
ZipFile inZip = null;
ZipFile outZip = null;
try
{
inZip = new ZipFile(inArchive);
outZip = new ZipFile(outArchive);
List<string> tempNames = new List<string>();
List<string> originalNames = new List<string>();
int I = 0;
foreach (ZipEntry entry in inZip)
{
if (!entry.IsDirectory)
{
string tempName = Path.Combine(tempPath, "tmp.tmp");
string oldName = entry.FileName;
byte[] buffer = new byte[4026];
Stream inStream = null;
FileStream stream = null;
try
{
inStream = entry.OpenReader();
stream = new FileStream(tempName, FileMode.Create, FileAccess.ReadWrite);
int size = 0;
while ((size = inStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, size);
}
inStream.Close();
stream.Flush();
stream.Close();
inStream = new FileStream(tempName, FileMode.Open, FileAccess.Read);
outZip.AddEntry(oldName, inStream);
outZip.Save();
}
catch (Exception exe)
{
throw exe;
}
finally
{
try { inStream.Close(); }
catch (Exception ignore) { }
try { stream.Close(); }
catch (Exception ignore) { }
}
}
}
}
catch (Exception e)
{
throw e;
}
}
One issue that I see is that you are opening the output zip file using File.OpenWrite(), which will replace the existing output file rather than merging new entries into it.
There is an example on the SharpDevelop Wiki that gives an example of updating a zip file using memory streams. It can be found at http://wiki.sharpdevelop.net/SharpZipLib_Updating.ashx#Updating_a_zip_file_in_memory_1
The following is some simpler code that will read from the input zip and write to the output zip, which potentially already exists. It does not require writing temporary data to the filesystem.
public static void CopyToZip(string inArchive, string outArchive)
{
using (inZip = new ZipFile(inArchive),
outZip = new ZipFile(outArchive))
{
Func<String,Func<String,Stream>> getInStreamReturner = (name) => {
return new Func<String,Stream>(a){ return inZip[a].OpenReader(); };
};
foreach (ZipEntry entry in inZip)
{
if (!entry.IsDirectory)
{
string zipEntryName = entry.FileName;
outZip.AddEntry(zipEntryName,
getInStreamReturner(zipEntryName),
(name, stream) => stream.Close() );
}
}
outZip.Save();
}
}
Notes:
This approach uses the ZipFile.AddEntry overload that accepts two delegates: an opener and a closer. These functions get called at the time of ZipFile.Save. The former delegate needs to open and return the stream that contains the data to be zipped. The latter delegate needs to just close the stream.
It is necessary to define the getInStreamReturner Func , in order to open the right stream at the time of ZipFile.Save. Bear in mind that the zipEntryName changes value each time through the loop. Also ZipEntry.OpenReader() opens a stream on the actual zip data, which reads-and-decompresses as it goes. You can have only one of those open, at any one time, per ZipFile. getInStreamReturner creates a new function each time through the loop, thereby creating a closure to retain the value of the zipEntryName for reference at the time of ZipFile.Save.
This approach will fail if there are name clashes between the inArchive and outArchive. To avoid that you'd need to check for that and somehow avoid it. Either contrive a new, unique name, or skip adding entries with duplicate names into the outarchive.
I haven't tested this.
While this approach does not write to the filesystem, it does decompress and recompress file data. There is an open request to provide a feature to DotNetZip to migrate entries without that decompress/recompress jump. I haven't implemented that yet.

FileStream and ObjectDisposedException in .NET CF

public byte[] GetFile(string filename)
{
FileStream aStream = File.Open(filename, FileMode.Open, FileAccess.Read);
BinaryReader binReader = new BinaryReader(aStream);
binReader.BaseStream.Position = 0;
byte[] binFile = binReader.ReadBytes(Convert.ToInt32(binReader.BaseStream.Length));
binReader.Close();
return binFile;
}
I run this method for a number of filepaths, problem is whenever a file cannot be accessed with File.Open (because it is used by another process) I get:
'aStream.Position' threw an exception of type 'System.ObjectDisposedException'
on the following line:
binReader.BaseStream.Position = 0;
And seldom I get
{System.IO.IOException: The process can not access the file '\folder\file.txt' because it is being used by another process.}
This is the exception I want. So why is the object disposed most of the times?
Note: I first had the FileStream line in a using statement but removed it because I thought that might have disposed the object. But the problem remains.
Edit: Using Compact Framework, which doesn't have ReadAllBytes.
Maybe that part of the time your FileStream is throwing the IOException whenever your file is in use, and at other times, perhaps, you are getting the ObjectDisposedException because your array is not initialized.
Obviously, I can not test this theory.
See if you can copy-n-paste this one with good results:
public byte[] GetFile(string filename)
{
byte[] binFile = null;
try
{
using (var aStream = File.Open(filename, FileMode.Open, FileAccess.Read))
{
BinaryReader binReader = new BinaryReader(aStream);
binFile = new byte[binReader.BaseStream.Length];
binReader.BaseStream.Position = 0; // <= this step should not be necessary
binFile = binReader.ReadBytes(binReader.BaseStream.Length);
binReader.Close();
}
} catch (IOException err) {
// file is being used by another process.
} catch (ObjectDisposedException err) {
// I am guessing you would never see this because your binFile is not disposed
}
return binFile;
}
Be sure to check for null return variables!
EDIT:
I wrote (what I think is) a simpler version. I tested it, and it seems to work OK. I also prefer Read() overload to ReadBytes(), because I know how much data was pulled in.
First, is the test function that calls the method for every image in my Pictures folder:
public void Test() {
DirectoryInfo dir = new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.Personal));
foreach (var subDir in dir.GetDirectories()) {
if (-1 < subDir.Name.ToLower().IndexOf("pictures")) {
foreach (var file in subDir.GetFiles()) {
byte[] data = GetFile(file.FullName);
if (data != null) {
Console.WriteLine(data.Length);
}
}
}
}
}
public byte[] GetFile(string filename) {
byte[] result = null;
try {
if (File.Exists(filename)) {
int len = 0;
FileInfo file = new FileInfo(filename);
byte[] data = new byte[file.Length];
using (BinaryReader br = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read))) {
len = br.Read(data, 0, data.Length);
br.Close();
}
if (0 < len) {
if (len == data.Length) {
return data;
} else {
// this section of code was never triggered in my tests;
// however, it is good to keep it as a backup.
byte[] dat2 = new byte[len];
Array.Copy(data, dat2, len);
return dat2;
}
}
}
} catch (IOException err) {
// file is being used by another process.
} catch (ObjectDisposedException err) {
// I am guessing you would never see this because your binFile is not disposed
}
return result;
}
I don't see any reason why these would not work - unless you are having an int overflow.
Just use this:
byte[] contents = File.ReadAllBytes(filename);
Why don't you simply use
public byte[] GetFile(string filename)
{
try { return File.ReadAllBytes(filename); }
catch { return null; }
}
Just for fun, you could even define an extension method
public static class Extensions
{
public static byte[] GetFile(this string filename)
{
try { return File.ReadAllBytes(filename); }
catch { return null; }
}
}
so you could do byte[] myfile = filename.GetFile();.
Remember you must check that return is not null before proceed:
if (myfile != null)
{
// Do what you need
}

Error on making resumeable download in c#

I was trying to test a resumable download using c#. I found that add range will help by looking at some blogs. But in the following code add range have no meaning.
Guys Suggest me how to solve the issue.
What method will be effective to make a Resumable download??
HttpWebRequest myrequest = null;
HttpWebResponse myresponse = null;
private int interval=2048;
public bool set_url(string todonwloads,string tosaves)
{
this.todownload = todonwloads;
this.tosave = tosaves;
return true;
}
public bool start_download()
{
myrequest = (HttpWebRequest)WebRequest.Create(this.todownload);
// it the following code.
//If i dont write addrange. It will download same portion of the file.
myrequest.AddRange(4000,8000);
try
{
myresponse = (HttpWebResponse)myrequest.GetResponse();
if (myresponse.StatusCode == HttpStatusCode.OK)
{
Stream ReceiveSteam = myresponse.GetResponseStream();
FileStream fs = new FileStream(
this.tosave,
FileMode.Create,
FileAccess.Write,
FileShare.None);
int reads;
byte[] buffer = new byte[this.interval];
while ((reads = ReceiveSteam.Read(
buffer,
0,
this.interval)) > 0)
{
fs.Write(buffer, 0, reads);
}
return true;
}
}
catch (WebException ex)
{
throw ex;
}
finally
{
if (myresponse != null)
{
myresponse.Close();
}
}
return false;
}
You currently create and overwrite the file every time you download a section of the file:
// Overwrites the file each time -\/
... = new FileStream(this.tosave, FileMode.Create, ...
You instead need to open or create the file using FileMode.OpenOrCreate, then seek to the last section of the file you wrote to:
// seek to the last end offset, you'll need to save this somehow
fs.Seek(lastOffset, SeekOrigin.Begin);
int reads;
byte[] buffer = new byte[this.interval];
while ((reads = ReceiveSteam.Read(buffer, 0, this.interval)) > 0)
{
fs.Write(buffer, 0, reads);
lastOffset += reads;
}

Categories