简体   繁体   中英

How do i know using httpwebrequest and webresponse when a file download is completed?

private void downloadFile(Int32 fileNr)
        {
            FileStream writer = null;
            m_currentFileSize = 0;
            fireEventFromBgw(Event.FileDownloadAttempting);

            FileInfo file = this.Files[fileNr];
            FileInfo fileFirstDateTime = this.Files[0];
            FileInfo fileLastDateTime = this.Files[19];
            Int64 size = 0;

            Byte[] readBytes = new Byte[this.PackageSize];
            Int32 currentPackageSize;
            System.Diagnostics.Stopwatch speedTimer = new System.Diagnostics.Stopwatch();
            Int32 readings = 0;
            Exception exc = null;
            writer = LocalDirectorySettings(file);
            HttpWebRequest webReq;
            HttpWebResponse webResp = null;

            try
            {
                webReq = (HttpWebRequest)System.Net.WebRequest.Create(this.Files[fileNr].Path);
                webResp = (HttpWebResponse)webReq.GetResponse();

                size = webResp.ContentLength;
            }
            catch (Exception ex) { exc = ex; }

            m_currentFileSize = size;
            fireEventFromBgw(Event.FileDownloadStarted);

            if (exc != null)
            {
                bgwDownloader.ReportProgress((Int32)InvokeType.FileDownloadFailedRaiser, exc);
            }
            else
            {
                m_currentFileProgress = 0;
                while (m_currentFileProgress < size && !bgwDownloader.CancellationPending)
                {
                    while (this.IsPaused) { System.Threading.Thread.Sleep(100); }

                    speedTimer.Start();

                    currentPackageSize = webResp.GetResponseStream().Read(readBytes, 0, this.PackageSize);

                    m_currentFileProgress += currentPackageSize;
                    m_totalProgress += currentPackageSize;
                    fireEventFromBgw(Event.ProgressChanged);
                    try
                    {
                        writer.Write(readBytes, 0, currentPackageSize);
                    }
                    catch(Exception eee)
                    {
                        string myeee = eee.ToString();
                    }
                    readings += 1;

                    if (readings >= this.StopWatchCyclesAmount)
                    {
                        m_currentSpeed = (Int32)(this.PackageSize * StopWatchCyclesAmount * 1000 / (speedTimer.ElapsedMilliseconds + 1));
                        speedTimer.Reset();
                        readings = 0;
                    }
                }

                speedTimer.Stop();
                writer.Close();
                webResp.Close();
                if (!bgwDownloader.CancellationPending) { fireEventFromBgw(Event.FileDownloadSucceeded); }
            }
            fireEventFromBgw(Event.FileDownloadStopped);
        }

The bgwDownloader

private BackgroundWorker bgwDownloader = new BackgroundWorker();

The dowork event

private void bgwDownloader_DoWork(object sender, DoWorkEventArgs e)
        {
            Int32 fileNr = 0;
            countFilesNames = 0;

            if (this.SupportsProgress) { calculateFilesSize(); }

            if (!Directory.Exists(this.LocalDirectory)) { Directory.CreateDirectory(this.LocalDirectory); }

            while (fileNr < this.Files.Count && !bgwDownloader.CancellationPending)
            {
                m_fileNr = fileNr;
                downloadFile(fileNr);

                if (bgwDownloader.CancellationPending)
                {
                    fireEventFromBgw(Event.DeletingFilesAfterCancel);
                    cleanUpFiles(this.DeleteCompletedFilesAfterCancel ? 0 : m_fileNr, this.DeleteCompletedFilesAfterCancel ? m_fileNr + 1 : 1);
                }
                else
                {
                    fileNr += 1;
                }
            }
        }

In the backgroundworker completed event it's getting to the completed event only when all the files download completed.

But i need to to create event for each file download completed. The question if i need ot do it somehow with the backgroundworker or the httpwebrequest webresponde ? And how ?

If it's needed i will upload the whole class it's a bit long.

Update

This is in form1 how i subscribe to the FileDownloadSucceeded event:

downloader.FileDownloadSucceeded += new EventHandler(downloader_Succeeded);

Then in the event

private void downloader_Succeeded(object sender, EventArgs e)
        {
            countFilesDownloaded++;
            label6.Text = countFilesDownloaded.ToString();
            RichTextBoxExtensions.UpdateText(richTextBox1, "Ready: ", "Downloaded: ", Color.Green);
        }

The problem is when i put a breakpoint inside the event on the last line the RichTextBoxExtensions like it's getting there once. The downloaded file is 0 bytes size. Then i make continue it stop in this event once again second time this time the file is in the right size fully downloaded or written.

So i need somehow to check in this event when it finished the download complete. How can i do it ?

I want to make some manipulation on the downloaded file/s in this event but i need to make sure the file was downloaded finished and i checked now with a breakpoint and only on the second time it's getting to the event the file is completed downloaded/written to the hard disk.

Update

My main goal here is that i added this method to form1

public static Image[] GetFramesFromAnimatedGIF(Image IMG)
        {
            List<Image> IMGs = new List<Image>();
            int Length = IMG.GetFrameCount(FrameDimension.Time);

            for (int i = 0; i < Length; i++)
            {
                IMG.SelectActiveFrame(FrameDimension.Time, i);
                IMGs.Add(new Bitmap(IMG));
                IMG.Dispose();
            }

            return IMGs.ToArray();
        }

And i want that each file that was downloaded to extract/parse the frames gifs images from the file all the files are animated gifs so in the FileDownloadSucceeded event i added before the line:

Image img = new Bitmap(downloader.fileName);

The event

private void downloader_Succeeded(object sender, EventArgs e)
        {
            countFilesDownloaded++;
            label6.Text = countFilesDownloaded.ToString();
            RichTextBoxExtensions.UpdateText(richTextBox1, "Ready: ", "Downloaded: ", Color.Green);
            Image img = new Bitmap(downloader.fileName);
        }

In fileName i see: C:\\New folder (3)\\Countries\\Europe\\07032017_223558\\Europe---07032017_223558384.gif

The file is exist on the hard disk. But i'm getting exception on this line:

Image img = new Bitmap(downloader.fileName);

System.Reflection.TargetInvocationException was unhandled
  HResult=-2146232828
  Message=Exception has been thrown by the target of an invocation.
  Source=mscorlib
  StackTrace:
       at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
       at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
       at System.Delegate.DynamicInvokeImpl(Object[] args)
       at System.Windows.Forms.Control.InvokeMarshaledCallbackDo(ThreadMethodEntry tme)
       at System.Windows.Forms.Control.InvokeMarshaledCallbackHelper(Object obj)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Windows.Forms.Control.InvokeMarshaledCallback(ThreadMethodEntry tme)
       at System.Windows.Forms.Control.InvokeMarshaledCallbacks()
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at DownloaderPro.Program.Main() in C:\Users\Chocolade\Documents\Visual Studio 2015\Projects\DownloaderPro\DownloaderPro\DownloaderPro\Program.cs:line 19
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
       HResult=-2147024809
       Message=Parameter is not valid.
       Source=System.Drawing
       StackTrace:
            at System.Drawing.Bitmap..ctor(String filename)
            at DownloaderPro.Form1.downloader_Succeeded(Object sender, EventArgs e) in C:\Users\Chocolade\Documents\Visual Studio 2015\Projects\DownloaderPro\DownloaderPro\DownloaderPro\Form1.cs:line 347
            at DownloaderPro.FileDownloader.bgwDownloader_ProgressChanged(Object sender, ProgressChangedEventArgs e) in C:\Users\Chocolade\Documents\Visual Studio 2015\Projects\DownloaderPro\DownloaderPro\DownloaderPro\FileDownloader.cs:line 549
            at System.ComponentModel.BackgroundWorker.OnProgressChanged(ProgressChangedEventArgs e)
            at System.ComponentModel.BackgroundWorker.ProgressReporter(Object arg)
       InnerException: 

This is the complete class with the backgroundworker:

Class FileDownloader

And this is the project i used winrar:

Project

As far as I can see there is allready an event firing when a filedownload is completed.

fireEventFromBgw(Event.FileDownloadSucceeded)

Just subscribe to it when creating your backgroundworker.

EDIT:

You only uploded the sln file. Not much to see there. After looking to the code of FileDownloader.cs it looks like you didn´t wrote this "monster" on your own.

I´d like to suggest a different approuch:

 WebClient client = new WebClient();
 client.DownloadFile(source, target);

where source is the url and target the Path where to download to. For simple pictures it should do the trick. Thist approuch is sync.

After that:

var frames = GetFramesFromAnimatedGIF(new Bitmap(target));

For multiple Files put all in a loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM