1

我有一些代码使用任务通过 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 回答