我很难完成某件事。
我正在使用 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/