1

Task を使用して Web サービス経由でファイルを転送するコードが少しあります。ただし、ネットワークが切断されたりタイムアウトが発生したりすると、ファイルが不完全になります。私は本当にこのサービスを可能な限り信頼できるものにしようとしていますが、チャンクが送信されなかったときにトラップし、それを複数回再送信しようとするコードを実際にどこから追加し始めればよいのかよくわかりません。それが完了するまで次のチャンクを送信します。そのチャンクを X 回以上再送信できない場合は、完全に失敗してイベントをログに記録します。

誰でも何か提案できますか?

Action<Guid, string> action = (smGuid, pubAttFullPath) =>
        {
            try
            {
                //Set filename from object
                string FileName;
                FileName = System.IO.Path.GetFileName(pubAttFullPath.ToString());

                //Declare Web Service
                TransferFile.TransferFileSoapClient ws_TransferFile = new TransferFile.TransferFileSoapClient();

                //
                bool transfercompleted = false;
                using (FileStream fs = new FileStream(
                     pubAttFullPath.ToString(),
                     FileMode.Open,
                     FileAccess.Read,
                     FileShare.Read))
                {
                    //Declare Buffers and Counts
                    byte[] buffer = new byte[49152];
                    long fileSize = fs.Length;
                    long totalReadCount = 0;
                    int readCount;
                    float percentageComplete = 0;

                    //Loop and copy file until it changes to not exactly the same byte count as the buffer
                    //which means the file is about to complete.
                    while ((readCount = fs.Read(buffer, 0, buffer.Length)) > 0)
                    {
                        if (!transfercompleted)
                        {

                            totalReadCount += readCount;
                            byte[] bytesToTransfer;

                            if (readCount == buffer.Length)
                            {
                                //Copy bytes until buffer is different
                                bytesToTransfer = buffer;
                                ws_TransferFile.WriteBinaryFile("ABCD", bytesToTransfer, FileName);
                                percentageComplete = (totalReadCount / (float)fileSize * 100);
                                percentageComplete = (float)Math.Round(percentageComplete, 2, MidpointRounding.ToEven);
                                //Update progress to DB

                                InsertProgress.InsertProgressSoapClient ws_InsertProgress = new InsertProgress.InsertProgressSoapClient();
                                if (percentageComplete == 10.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 10.0);
                                }
                                if (percentageComplete == 20.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 20.0);
                                }
                                if (percentageComplete == 30.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 30.0);
                                }
                                if (percentageComplete == 40.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 40.0);
                                }
                                if (percentageComplete == 50.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 50.0);
                                }
                                if (percentageComplete == 60.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 60.0);
                                }
                                if (percentageComplete == 70.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 70.0);
                                }
                                if (percentageComplete == 80.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 80.0);
                                }
                                if (percentageComplete == 90.00)
                                {
                                    ws_InsertProgress.InsertProgressService(smGuid.ToString(), 90.0);
                                }
                            }
                            else
                            {
                                // Only a part is requred to upload,
                                // copy that part.
                                List<byte> b = new List<byte>(buffer);
                                bytesToTransfer = b.GetRange(0, readCount).ToArray();
                                ws_TransferFile.WriteBinaryFile("ABCD", bytesToTransfer, FileName);
                                percentageComplete = 100;

                                //Insert Progress as complete
                                InsertProgress.InsertProgressSoapClient ws_InsertProgress = new InsertProgress.InsertProgressSoapClient();
                                ws_InsertProgress.InsertProgressService(smGuid.ToString(), 100);
                                transfercompleted = true;
                                fs.Close();
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry("Application", ex.Message.ToString(), EventLogEntryType.Error);
            }
4

1 に答える 1

0

Web サービスはファイル転送には適していません。私はそれを数回使用しましたが、転送される追加のデータの量は、転送されるデータのサイズを単純なハンドラーを使用してファイルを送信するよりも1,5〜2倍大きくします。ハンドラーを使用すると、問題なく同じことができます。適切な進行状況の処理と再開で多くの問題が発生します。httphandler の使用を再考する必要があります。Web サービスを使用したい場合は、次のような良い例があります。

http://msdn.microsoft.com/en-us/library/ms172362%28v=vs.85%29.aspx

IHttpHandlerを使用する場合は、以下を参照してください。

http://msdn.microsoft.com/en-us/library/ms228090%28v=vs.100%29.aspx

そして、次のコードを使用して、再試行/再開を適切に処理できます。

                using (Stream stream = new FileStream(
                 pubAttFullPath.ToString(),
                 FileMode.Open,
                 FileAccess.Read,
                 FileShare.Read))
                {
                    context.Response.AddHeader("Accept-Ranges", "bytes");
                    context.Response.Buffer = false;

                    if (context.Request.Headers["Range"] != null)
                    {
                        context.Response.StatusCode = 206;
                        string[] range = context.Request.Headers["Range"].Split(new[] { '=', '-' });
                        startBytes = Convert.ToInt32(range[1]);
                    }

                    int dataToRead = size - startBytes;

                    context.Response.ContentType = "application/octet-stream";
                    context.Response.AddHeader("Content-Length", dataToRead.ToString());
                    context.Response.AddHeader("Connection", "Keep-Alive");
                    context.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8));

                    if (startBytes > 0)
                    {
                        context.Response.AddHeader("Content-Range", string.Format(" bytes {0}-{1}/{2}", startBytes, size - 1, size));
                        stream.Seek(startBytes, SeekOrigin.Begin);
                    }

                    while (dataToRead > 0)
                    {
                        // Verify that the client is connected.
                        if (context.Response.IsClientConnected)
                        {
                            // Read the data in buffer.
                            int length = stream.Read(buffer, 0, buffer.Length);

                            // Write the data to the current output stream.
                            context.Response.OutputStream.Write(buffer, 0, length);

                            // Flush the data to the HTML output.
                            context.Response.Flush();
                            dataToRead = dataToRead - length;
                        }
                        else
                        {
                            // prevent infinite loop if user disconnects
                            dataToRead = -1;
                        }
                    }
                }
于 2012-04-23T12:30:44.600 に答える