void DownloadWindow_Closed(object sender, EventArgs e)
 {
     try
     {
         if (cAWebClient != null)
         {
             cAWebClient.CancelAsync();
             cAWebClient.Dispose();
         }
     }
     catch { }
 }
示例#2
0
        internal string UploadFileToVF(string zipFile, string swiftFilename, UploadPercent callback)
        {
            Login();
            string fileUploadInfo = SendGetRequest(ServerUrl + "/testbench/client_upload_url?filename=" + HttpUtility.UrlEncode(swiftFilename));

            if (fileUploadInfo == null)
            {
                // job creation failed
                //job.Status = Job.StatusEnum.Failed;
                return(null);
            }
            int     maxProgress        = 0;
            object  maxProgressLock    = new object();
            dynamic fileUploadInfoJson = Newtonsoft.Json.Linq.JObject.Parse(fileUploadInfo);
            string  fileUploadUrl      = fileUploadInfoJson["url"].Value;

            try
            {
                try
                {
                    using (CookieAwareWebClient webClient = new CookieAwareWebClient())
                    {
                        webClient.cookies = this.AuthCookies;
                        webClient.Timeout = HTTP_WEB_TIMEOUT_BASE;
                        Semaphore progress  = new Semaphore(0, int.MaxValue);
                        Semaphore completed = new Semaphore(0, 1);
                        UploadFileCompletedEventArgs completedData = null;
                        webClient.UploadFileCompleted += delegate(object sender, UploadFileCompletedEventArgs e)
                        {
                            completedData = e;
                            completed.Release();
                        };
                        webClient.UploadProgressChanged += delegate(object sender, UploadProgressChangedEventArgs e)
                        {
                            lock (maxProgressLock)
                            {
                                int percentProgress = (int)(((double)e.BytesSent / e.TotalBytesToSend) * 99.0);
                                if (percentProgress > maxProgress)
                                {
                                    // e.ProgressPercentage is not correct, as (almost) all the time is spent uploading
                                    maxProgress = percentProgress;
                                    callback(maxProgress);
                                }
                            }
                            progress.Release();
                        };
                        webClient.UploadFileAsync(new Uri(fileUploadUrl), "PUT", zipFile);
                        while (true)
                        {
                            WaitHandle[] handles = new WaitHandle[] { completed, progress };
                            int          timeout = HTTP_WEB_TIMEOUT_BASE;
                            lock (maxProgressLock)
                            {
                                // Workaround for Fiddler proxy: Fiddler accepts all the data at once, then uploads to VF
                                if (maxProgress > 98)
                                {
                                    handles = new WaitHandle[] { completed };
                                    timeout = HTTP_WEB_REQUEST_TIMEOUT;
                                }
                            }
                            int handle = WaitHandle.WaitAny(handles, timeout);
                            if (handle == 0)
                            {
                                lock (maxProgressLock)
                                {
                                    maxProgress = 100;
                                    callback(maxProgress);
                                }
                                break;
                            }
                            if (handle == System.Threading.WaitHandle.WaitTimeout)
                            {
                                webClient.CancelAsync();
                                throw new WebException("Connection timed out");
                            }
                            if (handle != 1)
                            {
                                throw new Exception();
                            }
                        }

                        Trace.TraceInformation("Upload to S3 " + Encoding.UTF8.GetString(completedData.Result));
                        return(fileUploadUrl);
                    }
                }
                catch (System.Reflection.TargetInvocationException ex)
                {
                    throw ex.InnerException;
                }
            }
            catch (WebException ex)
            {
                Trace.TraceError("Error uploading to {0}. Exception follows", fileUploadUrl);
                Trace.TraceError(ex.ToString());
            }
            return(null);
        }
示例#3
0
        private async Task <string> DownloadResumeSupportAsync([NotNull] CookieAwareWebClient client,
                                                               [NotNull] FlexibleLoaderGetPreferredDestinationCallback getPreferredDestination,
                                                               [CanBeNull] FlexibleLoaderReportDestinationCallback reportDestination, [CanBeNull] Func <bool> checkIfPaused,
                                                               IProgress <long> progress, CancellationToken cancellation)
        {
            // Common variables
            string filename = null, selectedDestination = null, actualFootprint = null;
            Stream remoteData = null;

            var resumeSupported = ResumeSupported;

            try {
                // Read resume-related data and remove it to avoid conflicts
                var resumeDestination             = CacheStorage.Get <string>(_keyDestination);
                var resumePartiallyLoadedFilename = CacheStorage.Get <string>(_keyPartiallyLoadedFilename);
                var resumeLastWriteDate           = CacheStorage.Get <DateTime?>(_keyLastWriteDate);
                var resumePreviousFootprint       = CacheStorage.Get <string>(_keyFootprint);
                ClearResumeData();

                // Collect known information for destination callback
                var information = FlexibleLoaderMetaInformation.FromLoader(this);

                // Opening stream to read…
                var headRequest = HeadRequestSupported && resumeDestination != null;
                using (headRequest ? client.SetMethod("HEAD") : null) {
                    Logging.Warning($"Initial request: {(headRequest ? "HEAD" : "GET")}");
                    remoteData = await client.OpenReadTaskAsync(Url);
                }

                cancellation.ThrowIfCancellationRequested();

                // Maybe we’ll be lucky enough to load the most accurate data
                if (client.ResponseHeaders != null)
                {
                    if (long.TryParse(client.ResponseHeaders[HttpResponseHeader.ContentLength] ?? "",
                                      NumberStyles.Any, CultureInfo.InvariantCulture, out var length))
                    {
                        TotalSize = information.TotalSize = length;
                    }

                    if (TryGetFileName(client.ResponseHeaders, out var fileName))
                    {
                        FileName = information.FileName = fileName;
                    }

                    // For example, Google Drive responds with “none” and yet allows to download file partially,
                    // so this header will only be checked if value is not defined.
                    if (resumeSupported == null)
                    {
                        var accept = client.ResponseHeaders[HttpResponseHeader.AcceptRanges] ?? "";
                        if (accept.Contains("bytes"))
                        {
                            resumeSupported = true;
                        }
                        else if (accept.Contains("none"))
                        {
                            resumeSupported = false;
                        }
                    }

                    client.LogResponseHeaders();
                }

                // Was the file partially loaded before?
                var partiallyLoaded = ResumeSupported != false && resumePartiallyLoadedFilename != null
                        ? new FileInfo(FileUtils.EnsureFilenameIsValid(resumePartiallyLoadedFilename)) : null;
                if (partiallyLoaded != null)
                {
                    Logging.Warning("Not finished: " + partiallyLoaded);
                }

                // Does it still exist
                if (partiallyLoaded?.Exists != true)
                {
                    Logging.Warning($"Partially downloaded file “{partiallyLoaded?.FullName}” does not exist");
                    partiallyLoaded = null;
                }

                // If so, wasn’t it changed since the last time?
                if (partiallyLoaded?.LastWriteTime > resumeLastWriteDate + TimeSpan.FromMinutes(5))
                {
                    Logging.Warning($"Partially downloaded file is newer that it should be: {partiallyLoaded.LastWriteTime}, expected: {resumeLastWriteDate}");
                    partiallyLoaded = null;
                }

                // Looks like file is partially downloaded, but let’s ensure link still leads to the same content
                actualFootprint = GetFootprint(information, client.ResponseHeaders);
                if (partiallyLoaded != null && resumePreviousFootprint != actualFootprint)
                {
                    Logging.Warning($"Footprints don’t match: {resumePreviousFootprint}≠{actualFootprint}");
                    partiallyLoaded = null;
                }

                // Let’s check where to load data, which is potentially the most actual data at this point
                var destination = getPreferredDestination(Url, information);
                selectedDestination = destination.Filename;
                if (partiallyLoaded != null && (!destination.CanResumeDownload || !FileUtils.ArePathsEqual(selectedDestination, resumeDestination)))
                {
                    Logging.Warning($"Different destination chosen: {selectedDestination} (before: {resumeDestination})");
                    partiallyLoaded = null;
                }

                // TODO: Check that header?

                // Where to write?
                // ReSharper disable once MergeConditionalExpression
                filename = partiallyLoaded != null ? partiallyLoaded.FullName : FileUtils.EnsureUnique(true, destination.Filename);
                reportDestination?.Invoke(filename);

                // Set cancellation token
                cancellation.Register(o => client.CancelAsync(), null);

                // Open write stream
                if (partiallyLoaded != null)
                {
                    var rangeFrom = partiallyLoaded.Length;
                    using (client.SetRange(new Tuple <long, long>(rangeFrom, -1))) {
                        Logging.Warning($"Trying to resume download from {rangeFrom} bytes…");

                        remoteData.Dispose();
                        remoteData = await client.OpenReadTaskAsync(Url);

                        cancellation.ThrowIfCancellationRequested();
                        client.LogResponseHeaders();

                        // It’s unknown if resume is supported or not at this point
                        if (resumeSupported == null)
                        {
                            var bytes      = new byte[16];
                            var firstBytes = await remoteData.ReadAsync(bytes, 0, bytes.Length);

                            cancellation.ThrowIfCancellationRequested();

                            if (CouldBeBeginningOfAFile(bytes))
                            {
                                using (var file = File.Create(filename)) {
                                    Logging.Warning("File beginning found, restart download");
                                    file.Write(bytes, 0, firstBytes);
                                    await CopyToAsync(remoteData, file, checkIfPaused, progress, cancellation);

                                    cancellation.ThrowIfCancellationRequested();
                                }

                                Logging.Write("Download finished");
                                return(filename);
                            }

                            rangeFrom += firstBytes;
                        }

                        using (var file = new FileStream(filename, FileMode.Append, FileAccess.Write)) {
                            await CopyToAsync(remoteData, file, checkIfPaused, new Progress <long>(v => {
                                progress?.Report(v + rangeFrom);
                            }), cancellation);

                            cancellation.ThrowIfCancellationRequested();
                        }
                    }
                }
                else
                {
                    if (headRequest)
                    {
                        Logging.Warning("Re-open request to be GET");
                        remoteData.Dispose();
                        remoteData = await client.OpenReadTaskAsync(Url);
                    }

                    using (var file = File.Create(filename)) {
                        Logging.Debug("Downloading the whole file…");
                        await CopyToAsync(remoteData, file, checkIfPaused, progress, cancellation);

                        cancellation.ThrowIfCancellationRequested();
                    }
                }

                Logging.Write("Download finished");
                return(filename);
            } catch (Exception e) when(e is WebException || e.IsCancelled())
            {
                Logging.Write("Download is interrupted! Saving details to resume later…");
                var download = filename == null ? null : new FileInfo(filename);

                if (download?.Exists == true && filename.Length > 0)
                {
                    CacheStorage.Set(_keyDestination, selectedDestination);
                    CacheStorage.Set(_keyPartiallyLoadedFilename, filename);
                    CacheStorage.Set(_keyFootprint, actualFootprint);
                    CacheStorage.Set(_keyLastWriteDate, download.LastWriteTime);
                }
                else
                {
                    ClearResumeData();
                }

                throw;
            } finally {
                remoteData?.Dispose();
            }
        }
 public void StopDownloadAsync()
 {
     webClient.CancelAsync();
 }