在文件下载完成后,我如何知道使用httpwebrequest和webresponse?

时间:2017-03-07 19:48:48

标签: c# .net winforms

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

bgwDownloader

private BackgroundWorker bgwDownloader = new BackgroundWorker();

dowork事件

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

在backgroundworker完成的活动中,只有当所有文件下载完成后才能进入已完成的活动。

但我需要为每个文件下载完成创建事件。 如果我需要ot以某种方式与backgroundworker或httpwebrequest webresponde做这个问题?怎么样?

如果需要,我会将整个课程上传一段时间。

更新

这是form1我如何订阅FileDownloadSucceeded事件:

downloader.FileDownloadSucceeded += new EventHandler(downloader_Succeeded);

然后在事件中

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

问题是当我在最后一行的事件中放置一个断点时,RichTextBoxExtensions就像它到达那里一样。下载的文件大小为0字节。然后我继续它在这个事件中再次停止第二次这个文件是完全下载或写入的正确大小。

因此,当完成下载完成后,我需要以某种方式检查此事件。 我该怎么办?

我希望在此事件中对下载的文件进行一些操作,但我需要确保文件已下载完成并且我现在使用断点检查并且仅在第二次它到达事件时文件是完成下载/写入硬盘。

更新

我的主要目标是将此方法添加到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();
        }

我希望下载的每个文件都能从文件中提取/解析帧gifs图像,所有文件都是GIF动画,所以我在行之前添加的FileDownloadSucceeded事件中添加:

Image img = new Bitmap(downloader.fileName);

事件

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

在fileName中,我看到:C:\ New folder(3)\ Countries \ Europe \ 07032017_223558 \ Europe --- 07032017_223558384.gif

该文件存在于硬盘上。但我在这条线上得到例外:

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: 

这是背景工作者的完整课程:

Class FileDownloader

这是我使用winrar的项目:

Project

1 个答案:

答案 0 :(得分:1)

据我所知,当文件下载完成时,已经有一个事件被触发。

fireEventFromBgw(Event.FileDownloadSucceeded)

在创建背景工作时只需订阅它。

编辑:

你只上传了sln文件。在那里看不多。 在查看FileDownloader.cs的代码后,看起来你没有自己编写这个“怪物”。

我想建议一个不同的approuch:

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

其中source是url,目标是要下载到的Path。对于简单的图片,它应该做的伎俩。这个approuch是同步。

之后:

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

对于多个文件,将所有文件放入循环中。