当我尝试从数据库下载50 MB文件时(这不是文件较小的问题),它会在中间停止,并在很长一段时间后再次恢复。我在忙什么?
代码,
SqlConnection con = new SqlConnection(ConnectionString);
SqlCommand cmd = new SqlCommand("DownloadFile", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 60;
cmd.Parameters.AddWithValue("@Id", Id);
try
{
conPortal.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
// File name
string fileName = reader.GetString(0);
// Total bytes to read
int dataToRead = reader.GetInt32(1);
Context.Server.ScriptTimeout = 600;
Context.Response.Buffer = true;
Context.Response.Clear();
Context.Response.ContentType = "application/octet-stream";
Context.Response.AddHeader("Content-Disposition",
"attachment; filename=\"" + fileName + "\";");
Context.Response.AddHeader("Content-Length", dataToRead.ToString());
int ChunkSize = 262144;
// Buffer to read 10K bytes in chunk
byte[] buffer = new Byte[ChunkSize];
long offset = 0;
long length;
// Read the bytes.
while (dataToRead > 0)
{
// Verify that the client is connected.
if (Context.Response.IsClientConnected)
{
// Read the data in buffer
length = reader.GetBytes(2, offset, buffer, 0, ChunkSize);
offset += ChunkSize;
// Write the data to the current output stream.
Context.Response.OutputStream.Write(buffer, 0, (int) length);
// Flush the data to the HTML output.
Context.Response.Flush();
buffer = new Byte[ChunkSize];
dataToRead = dataToRead - (int) length;
}
else
{
//prevent infinite loop if user disconnects
dataToRead = -1;
}
}
}
finally
{
cmd.Dispose();
}
答案 0 :(得分:4)
int ChunkSize = 262144;
你去,那是25 MB - 正好在50 MB下载的中间。尝试修改它,看看会发生什么。您将其设置为该特定值的任何原因?
答案 1 :(得分:3)
这不是您从SQL Server查询结果中流式传输内容的方式。您必须指定CommandBehavior.SequentialAccess
:
为DataReader提供了一种方法 处理包含列的行 大二进制值。而不是 加载整行, SequentialAccess启用 DataReader将数据作为流加载。 然后,您可以使用GetBytes或 GetChars方法指定一个字节 开始读取操作的位置, 以及数据的有限缓冲区大小 被退回。
并且,正如其他人所指出的,25MB不是合理的缓冲块大小。尝试类似4K(典型TDS packet size)或16k(如果连接已加密,则为典型的SSL帧大小)。