首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用SqlDataReader MVC在FileStreamResult中使用ASP.NET时请求未完成

使用SqlDataReader MVC在FileStreamResult中使用ASP.NET时请求未完成
EN

Stack Overflow用户
提问于 2015-07-28 13:06:26
回答 3查看 2.9K关注 0票数 7

出于性能考虑,我使用SqlConnectionSqlReaderStream从Server数据库返回byte[]

代码语言:javascript
运行
复制
private static SqlConnection GetConnection()
{
    var sqlConnectionStringBuilder =
        new SqlConnectionStringBuilder(
            ConfigurationManager.ConnectionStrings["StudentsSystemEntities"].ConnectionString)
            {
                Pooling = true
            };
    var connection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString);
    connection.Open();
    return connection;
}

public FileDownloadModel GetFileById(Guid fileId)
{
    var connection = GetConnection();
    var command = new SqlCommand(
        @"SELECT [FileSize], [FileExtension], [Content] FROM [dbo].[Files] WHERE [FileId] = @fileId;",
        connection);
    var paramFilename = new SqlParameter(@"fileId", SqlDbType.UniqueIdentifier) { Value = fileId };
    command.Parameters.Add(paramFilename);

    var reader = command.ExecuteReader(
        CommandBehavior.SequentialAccess | CommandBehavior.SingleResult
        | CommandBehavior.SingleRow | CommandBehavior.CloseConnection);

    if (reader.Read() == false) return null;

    var file = new FileDownloadModel
                    {
                        FileSize = reader.GetInt32(0),
                        FileExtension = reader.GetString(1),
                        Content = new SqlReaderStream(reader, 2)
                    };
    return file;
}

我正在ASP.NET MVC action中使用此ASP.NET方法。

代码语言:javascript
运行
复制
[HttpGet]
public ActionResult Get(string id)
{
    // Validations omitted

    var file = this.filesRepository.GetFileById(guid);

    this.Response.Cache.SetCacheability(HttpCacheability.Public);
    this.Response.Cache.SetMaxAge(TimeSpan.FromDays(365));
    this.Response.Cache.SetSlidingExpiration(true);

    this.Response.AddHeader("Content-Length", file.FileSize.ToString());
    var contentType = MimeMapping.GetMimeMapping(
        string.Format("file.{0}", file.FileExtension));
    // this.Response.BufferOutput = false;
    return new FileStreamResult(file.Content, contentType);
}

我将MVC FileStreamResultSqlReaderStream连接如下:

代码语言:javascript
运行
复制
return new FileStreamResult(file.Content, contentType);

当我试图使用Chrome (或Firefox.)加载资源时,会加载整个文件,但我得到了以下错误:

注意:请求尚未完成!

响应头:

代码语言:javascript
运行
复制
HTTP/1.1 200 OK
Cache-Control: public, max-age=31536000
Content-Length: 33429
Content-Type: image/png
Server: Microsoft-IIS/10.0
X-AspNetMvc-Version: 5.2
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcR---trimmed---G5n?=
X-Powered-By: ASP.NET
Date: Tue, 28 Jul 2015 13:02:55 GMT

附加信息:

  • 我不使用任何Chrome扩展
  • 问题仅在于给定的Get操作。所有其他操作正常加载。
  • FilesController (其中包含Get操作)直接从Controller类继承
  • 该文件正在成功加载,但浏览器仍在等待服务器:

  • 与我使用Firefox的问题完全相同

问题的可能原因是什么?

SqlReaderStream 类的源代码

代码语言:javascript
运行
复制
public class SqlReaderStream : Stream
{
    private readonly int columnIndex;

    private SqlDataReader reader;

    private long position;

    public SqlReaderStream(
        SqlDataReader reader, 
        int columnIndex)
    {
        this.reader = reader;
        this.columnIndex = columnIndex;
    }

    public override long Position
    {
        get { return this.position; }
        set { throw new NotImplementedException(); }
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanSeek
    {
        get { return false; }
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override long Length
    {
        get { throw new NotImplementedException(); }
    }

    public override void Flush()
    {
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        var bytesRead = this.reader.GetBytes(
            this.columnIndex, this.position, buffer, offset, count);
        this.position += bytesRead;
        return (int)bytesRead;
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotImplementedException();
    }

    public override void SetLength(long value)
    {
        throw new NotImplementedException();
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        throw new NotImplementedException();
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing && null != this.reader)
        {
            this.reader.Dispose();
            this.reader = null;
        }

        base.Dispose(disposing);
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-08-20 16:03:36

真正的问题是,在这一行:

代码语言:javascript
运行
复制
this.Response.AddHeader("Content-Length", file.FileSize.ToString());

您分发的文件大小是错误的,比实际文件大小还要大。这就是为什么浏览器在等待更多的内容。

若要快速检查这是否确实是问题所在,请将行修改为

代码语言:javascript
运行
复制
this.Response.AddHeader("Content-Length", (file.FileSize/10).ToString());

这将将文件的下载限制在所讨论文件的十分之一--但由于文件大小可能比一个数量级少得多,这些文件将有足够的数据来满足10 %的请求文件大小的要求,而且这个问题将不再是可复制的。

票数 2
EN

Stack Overflow用户

发布于 2015-08-18 20:38:56

我不会在SqlReaderStream中返回FileStreamResult,因为流不是可查找的。我想这可能是个问题。

尝试将Stream复制到MemoryStream字节数组,然后在GetFileById中返回它。

此外,如果在本地读取SqlReaderStream函数,则可以关闭到数据库的连接。

代码语言:javascript
运行
复制
return File(byteArray, contentType, name);
票数 5
EN

Stack Overflow用户

发布于 2015-08-18 09:09:15

这个问题与Chrome浏览器有关,只有当第一个请求未完成时。尝试使用Firefox或Safari。

有关更多信息,请参见下面的链接。http://www.codeproject.com/Questions/821716/PHP-serve-MP-Chrome-Provisional-headers-are-shown

"CAUTION: provisional headers are shown" in Chrome debugger

Chrome block requests

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31677242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档