So i have the following code:
WebClient webClient = new WebClient();
Stream data = webClient.OpenRead("http://awesomeurl.com/file.zip");
UnzipFromStream(data, #"c:/dir/");
And i would like to have the data of that stream in a progress bar, just like if you would use WebClient with .DownloadProgressChanged
I cant however seem to figure out how to make it work...
Please note: i am using ICSharpCode.SharpZipLib
UPDATE #1.1
Ok, i managed to get the following code to work (it downloads and unzips + the complete msg is shown), however the progress bar is not updating:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// first, we need to get the exact size (in bytes) of the file we are downloading
Uri url = new Uri(filename);
System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
response.Close();
// gets the size of the file in bytes
Int64 iSize = response.ContentLength;
// keeps track of the total bytes downloaded so we can update the progress bar
Int64 iRunningByteTotal = 0;
string outFolder = folder;
// use the webclient object to download the file
using (System.Net.WebClient webClient = new WebClient())
{
// open the file at the remote URL for reading
using (System.IO.Stream zipStream = webClient.OpenRead(filename))
{
ZipInputStream zipInputStream = new ZipInputStream(zipStream);
ZipEntry zipEntry = zipInputStream.GetNextEntry();
while (zipEntry != null)
{
String entryFileName = zipEntry.Name;
// to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
// Optionally match entrynames against a selection list here to skip as desired.
// The unpacked length is available in the zipEntry.Size property.
// Manipulate the output filename here as desired.
String fullZipToPath = Path.Combine(outFolder, entryFileName);
string directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
Directory.CreateDirectory(directoryName);
// Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
// of the file, but does not waste memory.
// The "using" will close the stream even if an exception occurs.
using (FileStream streamWriter = File.Create(fullZipToPath))
{
int iByteSize = 0;
byte[] buffer = new byte[iSize]; // 4K is optimum
StreamUtils.Copy(zipInputStream, streamWriter, buffer);
while ((iByteSize = zipStream.Read(buffer, 0, buffer.Length)) > 0)
{
iRunningByteTotal += iByteSize;
// calculate the progress out of a base "100"
double dIndex = (double)(iRunningByteTotal);
double dTotal = (double)iSize;
double dProgressPercentage = (dIndex / dTotal);
int iProgressPercentage = (int)(dProgressPercentage * 100);
// update the progress bar
backgroundWorker1.ReportProgress(iProgressPercentage);
}
}
zipEntry = zipInputStream.GetNextEntry();
}
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("File download complete");
}
Related
I'm trying to download a file from my DropBox account.
I get an error with
var task = Task.Run((Func<Task>)Download("", "largetest.mpk", folderName));
The error:
Cannot convert type 'System.Threading.Tasks.Task' to 'System.Func<System.Threading.Tasks.Task>
private void button1_Click(object sender, EventArgs e)
{
string folderName = #"c:\dropboxTest\test.exe";
var task = Task.Run((Func<Task>)Download("", "largetest.mpk", folderName));
task.Wait();
}
async Task Download(string folder, string targetfile, string localPath)
{
var dbx = new DropboxClient(Form1.api);
var response = await dbx.Files.DownloadAsync(folder + "/" + targetfile);
ulong fileSize = response.Response.Size;
const int bufferSize = 1024 * 1024;
var buffer = new byte[bufferSize];
string folderName = #"C:\dropboxTest\teasdfst.exe";
using (var stream = await response.GetContentAsStreamAsync())
{
using (var localfile = new FileStream(folderName, FileMode.OpenOrCreate))
{
var length = stream.Read(buffer, 0, bufferSize);
while (length > 0)
{
localfile.Write(buffer, 0, length);
// Console.WriteLine(localfile.);
var percentage = 100 * (ulong)localfile.Length / fileSize;
// Update progress bar with the percentage.
// progressBar.Value = (int)percentage
//Console.WriteLine(percentage);
length = stream.Read(buffer, 0, bufferSize);
}
}
}
}
You should write your function like this
void Download(string folder, string targetfile, string localPath)
{
var dbx = new DropboxClient(Form1.api);
var response = dbx.Files.Download(folder + "/" + targetfile);
ulong fileSize = response.Response.Size;
const int bufferSize = 1024 * 1024;
var buffer = new byte[bufferSize];
string folderName = #"C:\dropboxTest\teasdfst.exe";
using (var stream = response.GetContentAsStream())
{
using (var localfile = new FileStream(folderName, FileMode.OpenOrCreate))
{
var length = stream.Read(buffer, 0, bufferSize);
while (length > 0)
{
localfile.Write(buffer, 0, length);
// Console.WriteLine(localfile.);
var percentage = 100 * (ulong)localfile.Length / fileSize;
// Update progress bar with the percentage.
// progressBar.Value = (int)percentage
//Console.WriteLine(percentage);
length = stream.Read(buffer, 0, bufferSize);
}
}
}
}
and then call with Task.Run like below
private void button1_Click(object sender, EventArgs e)
{
string folderName = #"c:\dropboxTest\test.exe";
var task = Task.Run(() => Download("", "largetest.mpk", folderName));
task.Wait(); // remove this if you don't want to block UI thread.
}
Hope this helps !!
You do not need to do all of that. No conversions, no casts, no Task.Run.
Just write
const string folderName = #"c:\dropboxTest\test";
private async void button1_Click(object sender, EventArgs e)
{
await Download("", "largetest.mpk", folderName);
}
Note that we directly await the method call. Note how the call to Task.Wait has been removed.
Note that except in the case of event handlers, which need to be void methods, async methods should return Task objects. This is very important, especially for proper exception handling. This is the only case where async void is proper.
Your Download method, which should be renamed to DownloadAsync by convention, already has the proper return type Task and should not be changed in that regard.
My application, the file is downloaded from web server and is saved in IsolatedStorage(with same name from web file).
So, i want save multiple files on IsolatedStorage, from multiple URLs. What better way to do it?
private void sinc(object sender, EventArgs e)
{
client = new WebClient();
url = "http://infassteste.url.ph/json.html";
Uri uri = new Uri(url);
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(uri);
}
private void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
string strFileName = url.Substring(url.LastIndexOf("/") + 1, (url.Length - url.LastIndexOf("/") - 1));
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
// Path Storage
// *** If File Exists
if (isoStore.FileExists(strFileName))
{
isoStore.DeleteFile(strFileName);
}
IsolatedStorageFileStream dataFile = new IsolatedStorageFileStream(strFileName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, isoStore);
long fileLen = e.Result.Length;
byte[] b = new byte[fileLen];
e.Result.Read(b, 0, b.Length);
dataFile.Write(b, 0, b.Length);
dataFile.Flush();
object lenghtOfFile = dataFile.Length;
MessageBox.Show("Arquivo salvo!");
}
Collect all URIs to
List<URI> urls = new List<URI>();
Then go trough them using foreach loop and save files
foreach(Uri uri in urls)
{
// save files... perhaps client.OpenReadAsync(uri); ?
}
I followed the examples here: http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662940%28v=vs.105%29.aspx
I made the live preview and stuff work, but how can I take a picture? This is what i tried:
private PhotoCaptureDevice _photoCaptureDevice = null;
string strImageName = "IG_Temp";
private NokiaImagingSDKEffects _cameraEffect = null;
private MediaElement _mediaElement = null;
private CameraStreamSource _cameraStreamSource = null;
private Semaphore _cameraSemaphore = new Semaphore(1, 1);
MediaLibrary library = new MediaLibrary();
private async void ShutterButton_Click(object sender, RoutedEventArgs e)
{
if (_cameraSemaphore.WaitOne(100))
{
await _photoCaptureDevice.FocusAsync();
_cameraSemaphore.Release();
CameraCaptureSequence seq = _photoCaptureDevice.CreateCaptureSequence(1);
await seq.StartCaptureAsync();
MemoryStream captureStream1 = new MemoryStream();
// Assign the capture stream.
seq.Frames[0].CaptureStream = captureStream1.AsOutputStream();
try
{
// Set the position of the stream back to start
captureStream1.Seek(0, SeekOrigin.Begin);
// Save photo as JPEG to the local folder.
using (IsolatedStorageFile isStore = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream targetStream = isStore.OpenFile(strImageName, FileMode.Create, FileAccess.Write))
{
// Initialize the buffer for 4KB disk pages.
byte[] readBuffer = new byte[4096];
int bytesRead = -1;
// Copy the image to the local folder.
while ((bytesRead = captureStream1.Read(readBuffer, 0, readBuffer.Length)) > 0)
{
targetStream.Write(readBuffer, 0, bytesRead);
}
}
}
}
finally
{
// Close image stream
captureStream1.Close();
}
// Navigate to the next page
Dispatcher.BeginInvoke(() =>
{
NavigationService.Navigate(new Uri("/Edit.xaml?name=" + strImageName, UriKind.Relative));
});
}
}
But I will get an error:
System.InvalidOperationException
in line: await seq.StartCaptureAsync();
What am I doing wrong?
I have an app that downloads an image to the phone and depending on the image category it will assign it to a news feed. I am using this function:
private static void DownloadImage(string furl, string ids)
{
// Connect Again to the API
WebClient client = new WebClient();
client.Headers["NewsID"] = ids;
string url = "www.xxx.com/image/xyz";
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(new Uri(url));
}
private static void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (e.Error == null && !e.Cancelled)
{
Stream reply = null;
StreamReader s = null;
// i am not able to read the sender who is a webclient to retrieve the information it is always skipping it
WebClient wcd = sender as WebClient;
reply = (Stream)e.Result;
s = new StreamReader(reply);
//Console.WriteLine(s.ReadToEnd());
s.Close();
reply.Close();
if (!myIsolatedStorage.DirectoryExists("ImageCache"))
{
myIsolatedStorage.CreateDirectory("ImageCache");
}
//try
//{//((MS.Internal.InternalMemoryStream)(e.Result)).FinalUri.Segments[2]
var graphImage = e.Result;
Random rand = new Random();
string fileName = string.Format("ImageCache/{0}.jpg", rand.Next());
IsolatedStorageFileStream fileStream = myIsolatedStorage.CreateFile(fileName);
BitmapImage image = new BitmapImage();
image.SetSource(e.Result);
WriteableBitmap wb = new WriteableBitmap(image);
// Encode WriteableBitmap object to a JPEG stream.
Extensions.SaveJpeg(wb, fileStream, wb.PixelWidth, wb.PixelHeight, 0, 85);
fileStream.Close();
//}
//catch (IsolatedStorageException ex)
//{
//IsolatedStorageException
//Exception handle appropriately for your app
//}
}
}
}
In the OpenReadComplete function which I'm using to download the image, I want to get the newsID from the header, and then assign it to the image before saving it into the database. I can't seem to access the header. Is this possible?
I think you can read it with sender.
WebClient c = (WebClient)sender;
string id = c.Headers["NewsID"];
I know progress bars by themselves have been already asked to death, but I'm having trouble with one. I need to download a file via FTP, I'm using WebClient, the downloaded data has to be saved to a byte array, but WebClient.DownloadDataAsync can't return it directly, so I have to use the DownloadDataCompleted method to acces the data. Everything up till there is ok, but the problem is that I can't "pause" the IEnumerator block without blocking the whole thread, and if I don't pause it, the app crashes because the byte array doesn't exist when it tries to access it. When the file to download was in http I used WWW and had no problems, but it had to be moved to FTP. Using WebClient.DownloadData works, but I was asked to include a progress bar. Anyway, hereĀ“s the code:
IEnumerator DownloadGame(Dictionary<string, string> settingsDict)
{
statusText = "Starting download...";
WebClient request = new WebClient();
request.Credentials = new NetworkCredential("user", "password");
request.DownloadDataCompleted += DownloadDataCompleted;
//byte[] fileData = request.DownloadData(settingsDict["downloadlink"]); This works, but is no good since it blocks the thread
request.DownloadDataAsync(new Uri(settingsDict["downloadlink"]),"somefilepath");
//do{}while(!downloadFinished); This also works but blocks the thread anyway
//Process the update
string tmpRoot = TMPFolder();
string tmpFolder = tmpRoot + Application.platform + settingsDict["latestVersion"] + "/";
if (!UnzipUpdate(fileData, tmpFolder))//fail here, in this case fileData is global
{
DeleteDirectory(tmpRoot);
yield break;
}
if (!ProcessUpdateData(tmpFolder))
{
DeleteDirectory(tmpRoot);
yield break;
}
DeleteDirectory(tmpRoot);
settingsDict["thisVersion"] = GetNextVersion();
}
void DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e){
fileData = e.Result;
downloadFinished = true;
}
you can use something like this based on a previous Stakoverflow post..
The easiest is to use BackgroundWorker and put your code into DoWork event handler. And report progress with BackgroundWorker.ReportProgress.
The basic idea:
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var ftpWebRequest = (FtpWebRequest)WebRequest.Create("ftp://xxx.com");
ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile; //or DownLoad
using (var inputStream = File.OpenRead(fileName))
using (var outputStream = ftpWebRequest.GetRequestStream())
{
var buffer = new byte[1024 * 1024];
int totalReadBytesCount = 0;
int readBytesCount;
while ((readBytesCount = inputStream.Read(buffer, 0, buffer.Length)) > 0)
{
outputStream.Write(buffer, 0, readBytesCount);
totalReadBytesCount += readBytesCount;
var progress = totalReadBytesCount * 100.0 / inputStream.Length;
backgroundWorker1.ReportProgress((int)progress);
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}
Make sure WorkerReportsProgress is enabled
backgroundWorker2.WorkerReportsProgress = true;
With BackgroundWorker you can also easily implement upload cancellation.