0

別のサーバーからダウンロードした複数のファイルの zip アーカイブを送信するカスタム アクションの結果を作成しました。

大量のコードで申し訳ありませんが、それがあります。

using ICSharpCode.SharpZipLib.Zip;

/// <summary>
/// Downloads the files using specified URLs and continuously streams zipped result to the client 
/// </summary>
public class MultipleFileZipResult : ActionResult
{
    private readonly ILog log;
    private const int BufferSize = 32 * 1024;

    /// <summary>
    /// Initializes a new instance of the <see cref="MultipleFileZipResult"/> class.
    /// </summary>
    /// <param name="urls">The URLs to download.</param>
    /// <param name="resultFileName">Name of the result file.</param>
    /// <param name="log">The logger.</param>
    public MultipleFileZipResult(IEnumerable<DownloadableZipDescriptor> urls, string resultFileName, ILog log)
    {
        this.log = log;
        this.Urls = urls;
        this.ResultFileName = resultFileName;
    }

    /// <summary>
    /// Gets or sets the list of URLs to download.
    /// </summary>
    public IEnumerable<DownloadableZipDescriptor> Urls { get; set; }

    /// <summary>
    /// Gets or sets the name of the zip result file.
    /// </summary>
    public string ResultFileName { get; set; }

    /// <summary>
    /// Enables processing of the result of an action method by a custom type that inherits from the <see cref="T:System.Web.Mvc.ActionResult"/> class.
    /// </summary>
    /// <param name="context">The context in which the result is executed. The context information includes the controller, HTTP content, request context, and route data.</param>
    public override void ExecuteResult(ControllerContext context)
    {
        try
        {
            context.HttpContext.Response.ContentType = "application/zip";
            context.HttpContext.Response.CacheControl = "private";
            context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
            context.HttpContext.Response.AddHeader("content-disposition", string.Format("attachment; filename=\"{0}\"", this.ResultFileName));
            context.HttpContext.Response.Flush();

            var buffer = new byte[BufferSize];

            using (var zippedUploadStream = new ZipOutputStream(context.HttpContext.Response.OutputStream))
            {
                zippedUploadStream.SetLevel(0);

                foreach (var url in this.Urls)
                {
                    Stream downloadStream = null;
                    WebResponse response = null;

                    try
                    {
                        var request = WebRequest.Create(url.DownloadUrl);
                        request.Proxy = null;
                        response = request.GetResponse();
                        downloadStream = response.GetResponseStream();

                        if (downloadStream != null)
                        {
                            var zipEntry = new ZipEntry(url.SaveFileName);
                            zippedUploadStream.PutNextEntry(zipEntry);

                            int read;
                            while ((read = downloadStream.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                zippedUploadStream.Write(buffer, 0, read);
                                context.HttpContext.Response.Flush();
                            }
                        }
                    }
                    catch (Exception exception)
                    {
                        this.log.Error(exception);
                    }
                    finally
                    {
                        if (response != null)
                        {
                            response.Close();
                        }

                        if (downloadStream != null)
                        {
                            downloadStream.Close();
                        }
                    }

                    if (!context.HttpContext.Response.IsClientConnected)
                    {
                        break;
                    }
                }

                zippedUploadStream.Finish();
            }

            if (context.HttpContext.Response.IsClientConnected)
            {
                context.HttpContext.Response.Flush();
                context.HttpContext.Response.End();
            }
        }

        catch (Exception exception)
        {
            this.log.Error(exception);
            throw;
        }
    }
}

顧客がサーバーが配置されている同じネットワークから圧縮されたアーカイブをダウンロードしようとするまで、すべてがうまくいきました. 奇妙なことに、何らかの理由でダウンロードが正常に機能するためです。

唯一の顕著な違いは、私と彼のダウンロード速度です。彼のダウンロード速度は ~11 mbps ですが、私のは 0.4 mbps です。

ログに記録される例外:

System.Web.HttpException (0x800704CD): The remote host closed the connection. The error code is 0x800704CD.
   at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)
   at System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()
   at System.Web.HttpResponse.Flush(Boolean finalFlush)
   at System.Web.HttpResponseWrapper.Flush()

System.Web.HttpException (0x80004005): An error occurred while communicating with the remote host. The error code is 0x800703E3. ---> System.Runtime.InteropServices.COMException (0x800703E3): The I/O operation has been aborted because of either a thread exit or an application request. (Exception from HRESULT: 0x800703E3)
   at System.Web.Hosting.IIS7WorkerRequest.RaiseCommunicationError(Int32 result, Boolean throwOnDisconnect)
   at System.Web.Hosting.IIS7WorkerRequest.ExplicitFlush()
   at System.Web.HttpResponse.Flush(Boolean finalFlush)
   at System.Web.HttpResponseWrapper.Flush()
   at Infrastructure.MultipleFileZipResult.ExecuteResult(ControllerContext context)
4

0 に答える 0