The request is not completed when using SqlDataReader in FileStreamResult using ASP.NET MVC

For performance reasons, I use SqlConnection and SqlReaderStream to return the byte[] stream from the SQL Server database :

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

I use this GetFileById method in an ASP.NET MVC action :

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

I connect MVC FileStreamResult to SqlReaderStream in the following line:

 return new FileStreamResult(file.Content, contentType); 

When I try to upload a resource using Chrome (or Firefox ...) , the whole file is uploaded, but I get the following error:

ATTENTION: the request is not finished yet!

ATTENTION: the request is not finished yet!

Answer headers:

 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 

Additional Information:

  • I do not use Chrome extensions
  • The only problem is this Get action. All other actions are usually loaded.
  • FilesController (in which the Get action) inherits directly from the Controller class
  • The file loads successfully, but the browser is still waiting for the server: enter image description here
  • The same thing that I have with Firefox

What are the possible causes of the problem?

SqlReaderStream class source code

 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); } } 
+7
c # asp.net-mvc sqlconnection filestream
source share
3 answers

The real problem is that on this line:

 this.Response.AddHeader("Content-Length", file.FileSize.ToString()); 

you are giving the wrong file size, which is larger than the actual file size. This is why browsers are waiting for additional content.

To quickly verify that this is really a problem, change the line to the following

 this.Response.AddHeader("Content-Length", (file.FileSize/10).ToString()); 

This will limit the download to 1/10 of the file in question, but since the file sizes are probably much smaller than an order of magnitude, the files will have enough data to serve 10 percent of the requested files and the problem will no longer play.

+2
source share

I would not return SqlReaderStream to FileStreamResult , because the stream is not searchable . I think this could be a problem.

Try copying the Stream array to a MemoryStream or byte and instead return it to GetFileById .

In addition, you can close the database connection if you read the local SqlReaderStream function.

 return File(byteArray, contentType, name); 
+5
source share

This problem is related to the Chrome browser only when the first request is not completed. Try using Firefox or Safari.

See the links below for more information. http://www.codeproject.com/Questions/821716/PHP-serve-MP-Chrome-Provisional-headers-are-shown

"WARNING: preview headers shown" in the Chrome debugger

Chrome Block Requests

0
source share

All Articles