从数据库流文件内容

本文关键字:文件 数据库 | 更新日期: 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没有"流"支持(这里讨论),确保你是好的。