我很难完成任务。
我正在使用asp.net MVC 4构建一个mailclient。
我必须将与消息(不是附件)相关的图像下载到客户端浏览器。
现在我有了这个设置:
客户端浏览器 - >控制器/后端 - >邮件服务器
澄清:我有一个客户端请求,其中包含图像的内容ID,正确的邮箱,消息等。通过该信息,我可以从邮件服务器下载图像并将其上传到客户端。 现在来了困难的部分:我想要异步。我希望能够从邮件服务器下载一个512 KB的块,解码该部分,然后将其发送到客户端.fetch - decode - send ..只要浏览器获得图像的所有数据。
我只是不想先将所有数据先下载到服务器,然后创建一个包含所有数据的新内存流,并将其作为fileresult返回。我太害怕在我的内存中获取太大的文件并阻止其他进程等。
我打算使用这种方法上传真正的附件(可能是100的MB)。所以我稍后会需要这种方法。
现在我根本不知道如何实现这一点,因为我有一个连接到邮件服务器,我有一个连接到客户端。我必须将数据传递给新流或其他东西才能完成这项工作。
有人可以帮帮我吗?
编辑:澄清:不,我不能引用邮件服务器上的文件。我必须通过套接字将文件下载到服务器。
Edit2:http chuncked是解决方案吗?如果是的话,你能给我一个小例子吗?
答案 0 :(得分:4)
您只需要将数据从一个流(tcp连接到邮件服务器)复制到另一个(http连接到浏览器),对吧?如果要扩展,则需要使用this article中所述的非阻塞IO。因此,您需要从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);
}
}
以上代码未经测试且不包含错误处理,但它应该让您入门。