从数据库流文件内容
本文关键字:文件 数据库 | 更新日期: 2023-09-27 17:53:33
回到WebForms时代,我可以使用Response.OutputStream.Write()
和Response.Flush()
将文件数据块传输到客户端——因为我们正在流式传输的文件非常大,会消耗太多web服务器内存。我怎么能这样做,现在与新的MVC类,如FileStreamResult
?
我的确切情况是:DB包含VarBinary
列中的文件数据(CSV或XLS)。在WebForms实现中,我将System.Func
发送到DataAccess层,该层将遍历IDataReader
并使用System.Func
将内容流式传输到客户端。关键是我不希望web应用程序必须具有任何特定的数据库知识,包括IDataReader
。
我如何使用MVC实现相同的结果?
Func是(我在web层定义并向下发送到DB层):
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;
}
};
,在DB层,我们从DB SP(使用ExecuteReader语句)获得IDataReader
:
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();
}
如果您想重用FileStreamResult,则需要创建Stream
派生类,该类从DB读取数据并将该流传递给FileStreamResult
。
该方法的几个问题
- 动作结果是同步执行的,所以你的下载不会释放线程,而数据是从DB读取/发送-可能是ok的少量并行下载。要绕过你可能需要使用处理程序或直接从异步动作下载(感觉错误的MVC方法)
- 至少旧版本的
FileStreamResult
没有"流"支持(这里讨论),确保你是好的。