Пример #1
0
        /*
         * bool DownloadPage(DownloadMessage msg)
         * {
         *  var origmsg = msg;
         *  var tcs = new TaskCompletionSource<GotContentMessage>();
         *  var gotMsg = new GotContentMessage(msg);
         *  Client.GetAsync(msg.DownloadUri,HttpCompletionOption.ResponseContentRead)
         *      .ContinueWith((response, origmsg2) => { response.Result.Content.ReadAsStringAsync();
         *  return tcs.Task;
         *      })
         *      .ContinueWith(t2=> DoResponse(t2))
         *      .PipeTo(Self);
         *      return true;                                        // show ActorSystem we handled message [expect next one immediately!]
         * }
         */
        /// <summary>
        ///     process incoming DownloadMessage
        /// </summary>
        /// <param name="msg">incoming msg<see cref="DownloadMessage"/></param>
        /// <returns>true to state that message has been accepted</returns>
        internal bool DownloadPage(DownloadMessage msg)
        {
            var uri = msg.DownloadUri;

            SysDiag.Debug.Assert(uri.IsAbsoluteUri, $"DownloadActor.DownloadPage({uri}) called with non-absolute Url");
            var fs = msg.TargetPath;
            var fi = new FileInfo(fs);
            var dn = fi.DirectoryName;              // string representing the directory's full path

            if (Directory.Exists(dn))
            {
                if (msg.EnumDisposition == DownloadMessage.E_FileDisposition.LeaveIfExists &&
                    File.Exists(fs))
                {
                    var failmsg = new DownloadedMessage(msg, fs, HttpStatusCode.NotModified);
                    Sender.Tell(failmsg);
                }
            }
            else
            {
                _Log.Info("DownloadPage creating directory {0} for {1}.{2}", dn, fi.Name, fi.Extension);
                Directory.CreateDirectory(dn);
            }

            // preserve volatile state now (before t1 that starts hot) for use by subsequent completion
            var ctx1 = new Context1(Sender, msg);
            var t1   = Client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);  // returns Task<HttpResponseMessage>
            var t2A  = t1.ContinueWith((req, state) =>
            {
                var ctx1A  = state as Context1;                             // recover entry context
                var dlmsg  = ctx1A.DownloadMessage;
                var status = req.Result.StatusCode;
                if (req.IsFaulted)
                {
                    var s = "";
                    Console.WriteLine();
                    PostBack(dlmsg, ctx1A, status, req.Exception);
                }
                else
                {
                    var hrm = req.Result;
                    try
                    {
                        hrm.EnsureSuccessStatusCode();                      // throw if !IsSuccessStatusCode

                        // TODO: refine the destination filename.extn from the response

                        // TODO: decide if file already exists and if overwrite/transform

#pragma warning disable GCop302                                          // Since '{0}' implements IDisposable, wrap it in a using() statement
                        var outfs = new FileStream(fs, FileMode.Create); // open stream to write file. Disposed later !
#pragma warning restore GCop302                                          // Since '{0}' implements IDisposable, wrap it in a using() statement
                        _Log.Info($"DownloadActor.DownloadPage({msg.Url} => {fs}) started");
                    }
                    catch (Exception excp1)
                    {
                        PostBack(dlmsg, ctx1A, status, excp1);
                    }
                }
            }, ctx1);
            var t2 = t1.ContinueWith(GetStuff,
                                     ctx1,
                                     TaskContinuationOptions.OnlyOnRanToCompletion); // happy path (no cancel/fault)

            var t2F = t1.ContinueWith((req2, state) =>
            {
                var ctx1f = (Context1)state;
            },
                                      TaskContinuationOptions.NotOnRanToCompletion);
            var t3 = t2.ContinueWith(t_gotContent)
                     .PipeTo(Self);                              // Task

            return(true);                                        // show ActorSystem we handled message [expect next one immediately!]
        }
Пример #2
0
        /// <summary>
        /// The PostBack
        /// </summary>
        /// <param name="dlmsg">The dlmsg<see cref="DownloadMessage"/></param>
        /// <param name="ctx1A">The ctx1A<see cref="Context1"/></param>
        /// <param name="status">The status<see cref="HttpStatusCode"/></param>
        /// <param name="excp1">The excp1<see cref="Exception"/></param>
        private static void PostBack(DownloadMessage dlmsg, Context1 ctx1A, HttpStatusCode status, Exception excp1)
        {
            var failmsg = new DownloadedMessage(dlmsg, ctx1A.DownloadMessage.TargetPath, status, excp1);

            ctx1A.OrigSender.Tell(failmsg);
        }