来自DB的流文件内容

时间:2014-03-26 00:53:16

标签: c# asp.net asp.net-mvc filestream

回到WebForms时代,我可以使用Response.OutputStream.Write()Response.Flush()将文件数据块化到客户端 - 因为我们流式传输的文件很庞大,会占用过多的Web服务器内存。现在如何使用FileStreamResult等新的MVC类来完成这项工作?

我的确切情况是:数据库包含VarBinary列中的文件数据(CSV或XLS)。在WebForms实现中,我将System.Func发送到DataAccess层,该层将遍历IDataReader并使用System.Func将内容流式传输到客户端。关键是我不希望webapp必须具备任何特定的数据库知识,包括IDataReader

如何使用MVC获得相同的结果?

Func是(我在网络层定义并向下发送到数据库层):

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获取IDataReader(使用带有ExecuteReader的语句):

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();
}

1 个答案:

答案 0 :(得分:1)

如果要重用FileStreamResult,则需要创建Stream - 从DB读取数据并将该流传递给FileStreamResult的派生类。

将这种方法结合起来

  • 操作结果是同步执行的,因此在从DB / send读取数据时,下载不会释放线程 - 对于少量并行下载可能没问题。为了解决这个问题,您可能需要使用处理程序或直接从异步操作下载(对于MVC方法感觉不对)
  • 至少旧版FileStreamResult没有&#34;流媒体&#34;支持(discussed here),确保你没事。