c# - 异步下载文件到客户端

标签 c# asp.net-mvc asynchronous download

我很难完成某件事。

我正在使用 asp.net MVC 4 构建邮件客户端。

我现在必须将与消息相关的图像(不是附件)下载到客户端浏览器。

现在我有了这个设置:

客户端浏览器 -> Controller /后端 -> 邮件服务器

澄清一下:我有一个客户端请求,其中包含图像的内容 ID、正确的邮箱、消息等。有了这些信息,我可以从邮件服务器下载图像并将其上传到客户端。 现在是困难的部分:我想异步执行此操作。我希望能够从邮件服务器下载 512 KB 的 block ,解码该部分,并将其发送到客户端。获取 - 解码 - 发送 .. 只要浏览器获得图像的所有数据。

我只是不想首先将所有数据下载到服务器,然后用所有这些数据创建一个新的内存流并将其作为文件结果返回。我太害怕在我的内存中获取太大的文件并阻止其他进程等。

我也打算使用这种方法来上传真实附件(可能是 100 MB)。所以我稍后会需要这种方法。

现在我只是不知道如何实现这一点,因为我有一个到邮件服务器的连接,并且我有一个到客户端的连接。我必须将数据传递到新的流或其他东西才能完成这项工作..

有人可以帮帮我吗?

编辑:澄清一下:不,我不能引用邮件服务器上的文件。我必须通过套接字将文件下载到服务器。

Edit2:http chuncked 可以作为解决方案吗?如果是的话,你能举个小例子吗?

最佳答案

您只需要将数据从一个流(到邮件服务器的 tcp 连接)复制到另一个流(到浏览器的 http 连接),对吗?如果你想扩展,你需要使用非阻塞 IO,如 this article 中所述。 .因此,您需要从 IHttpAsyncHandler 实现中调用该文章中的代码。你最终会得到这样的结果:

class MyHandler : IHttpAsyncHandler
{
    public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
    {
        Stream src = null; // remote data source
        Stream dst = context.Response.OutputStream;

        // set content type, etc

        var res = new MyResult();

        AsynchCopy(src, dst, () =>
            {
                ((ManualResetEvent)res.AsyncWaitHandle).Set();
                cb(res);
                src.Close();
                dst.Flush();
            });

        return res;
    }

    public void EndProcessRequest(IAsyncResult result)
    {
    }

    public bool IsReusable
    {
        get { return true; }
    }

    public void ProcessRequest(HttpContext context)
    {
        throw new NotImplementedException();
    }

    class MyResult : IAsyncResult
    {
        public MyResult()
        {
            AsyncWaitHandle = new ManualResetEvent(false);
        }

        public object AsyncState
        {
            get { return null; }
        }

        public WaitHandle AsyncWaitHandle
        {
            get;
            private set;
        }

        public bool CompletedSynchronously
        {
            get { return false; }
        }

        public bool IsCompleted
        {
            get { return AsyncWaitHandle.WaitOne(0); }
        }
    }

    public static void AsynchCopy(Stream src, Stream dst, Action done)
    {
        byte[] buffer = new byte[2560];
        AsyncCallback readCallback = null, writeCallback = null;

        readCallback = (readResult) =>
        {
            int read = src.EndRead(readResult);
            if (read > 0)
            {
                dst.BeginWrite(buffer, 0, read, writeCallback, null);
            }
            else
            {
                done();
            }
        };

        writeCallback = (writeResult) =>
        {
            dst.EndWrite(writeResult);
            src.BeginRead(buffer, 0, buffer.Length, readCallback, null);
        };

        src.BeginRead(buffer, 0, buffer.Length, readCallback, null);
    }
}

以上代码未经测试且不包含错误处理,但它应该可以帮助您入门。

关于c# - 异步下载文件到客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13623772/

相关文章:

c# - 如何在Xamarin Forms中查看 'customized'?

c# - 将目录添加到列表 DirectoryInfo

asp.net-mvc - 为什么我们使用 ViewModel?

asp.net-mvc - Razor 页面中的多语言文本

c# - StringWriter.ToString() 正在破坏 xml C#

c# - 返回 LINQ 查询和 INSERT 数据

javascript - CORS 服务器端与客户端?为什么一个有效,而另一个却无效?

ios - 如何异步下载图片并保持顺序?

java - 同时处理多个常量套接字连接

python - 在 RQ 中重试失败的作业