C# 从数据库中传输文件内容
回到WebForms时代,我可以使用C# 从数据库中传输文件内容,c#,asp.net,asp.net-mvc,filestream,C#,Asp.net,Asp.net Mvc,Filestream,回到WebForms时代,我可以使用Response.OutputStream.Write()和Response.Flush()将文件数据分块到客户端,因为我们正在传输的文件非常大,会消耗太多web服务器内存。我现在如何使用新的MVC类,如FileStreamResult 我的确切情况是:DB在VarBinary列中包含文件数据(CSV或XLS)。在WebForms实现中,我向DataAccess层发送一个System.Func,该层将遍历IDataReader,并使用System.Func将内
Response.OutputStream.Write()
和Response.Flush()
将文件数据分块到客户端,因为我们正在传输的文件非常大,会消耗太多web服务器内存。我现在如何使用新的MVC类,如FileStreamResult
我的确切情况是:DB在VarBinary
列中包含文件数据(CSV或XLS)。在WebForms实现中,我向DataAccess层发送一个System.Func
,该层将遍历IDataReader
,并使用System.Func
将内容流式传输到客户端。关键是我不希望webapp必须具备任何特定的数据库知识,包括IDataReader
如何使用MVC实现相同的结果
Func是(我在web层中定义并发送到DB层):
如果要重用,需要创建从数据库读取数据的流
-派生类,并将该流传递到文件流结果
这种方法存在一些问题
- 操作结果是同步执行的,所以当从DB/send读取数据时,您的下载不会释放线程-对于少量并行下载可能是可以的。为了解决这个问题,您可能需要直接使用处理程序或从异步操作下载(MVC方法感觉不正确)
- 至少旧版本的
没有“流”支持(),请确保您没有问题李>FileStreamResult
stream
派生并实现Read
方法-对于这种情况来说应该足够了(需要几个其他方法,但不需要真正的实现)。很好的一点是,您可以从Read
返回的字节数少于所请求的字节数-因此每次请求时,只需从IDataReader
读取一些固定数量的字节。有关读取字节的一些示例,请参阅。对此很好奇……您不希望Web上有任何“DB引用”……但考虑到您正在将响应的引用(在Func中)向下传递到DB……DB层是否需要引用“Web stuff”?或者,因为只向DB传递Func参数,而不传递公共“Web参数”,所以不需要它?
Func<byte[], long, bool> partialUpdateFunc = (data, length) =>
{
if (Response.IsClientConnected)
{
// Write the data to the current output stream.
Response.OutputStream.Write(data, 0, (int) length);
// Flush the data to the HTML output.
Response.Flush();
return true;
}
else
{
return false;
}
};
using (var reader = conn.ExecuteReader())
{
if (reader.Read())
{
byte[] outByte = new byte[BufferSize];
long startIndex = 0;
// Read bytes into outByte[] and retain the number of bytes returned.
long retval = reader.GetBytes(0, startIndex, outByte, 0, BufferSize);
// Continue while there are bytes beyond the size of the buffer.
bool stillConnected = true;
while (retval == BufferSize)
{
stillConnected = partialUpdateFunc(outByte, retval);
if (!stillConnected)
{
break;
}
// Reposition start index to end of last buffer and fill buffer.
startIndex += BufferSize;
retval = reader.GetBytes(0, startIndex, outByte, 0, BufferSize);
}
// Write the remaining buffer.
if (stillConnected)
{
partialUpdateFunc(outByte, retval);
}
}
// Close the reader and the connection.
reader.Close();
}