我们有很多文件,以二进制形式保存在 SQL Server 数据库中。 我制作了一个 .ashx 文件,将这些文件传递给用户。 不幸的是,当文件变得相当大时,它会失败,并出现以下错误:
Overflow or underflow in the arithmetic operation
当我将二进制文件加载到 byte[] 中时,我认为它耗尽了内存。
所以,我的问题是,当它来自数据库表时,如何实现此功能,以 block 的形式读取(也许?)? Response.TransmitFile() 似乎也是一个不错的选择,但同样,这将如何与数据库一起使用?
下面代码中的 DB.GetReposFile() 从数据库获取文件。有多个字段用于输入: 文件名、内容类型、日期戳和 varbinary 形式的 FileContent。
这是我的功能,传递文件:
context.Response.Clear();
try
{
if (!String.IsNullOrEmpty(context.Request.QueryString["id"]))
{
int id = Int32.Parse(context.Request.QueryString["id"]);
DataTable dtbl = DB.GetReposFile(id);
string FileName = dtbl.Rows[0]["FileName"].ToString();
string Extension = FileName.Substring(FileName.LastIndexOf('.')).ToLower();
context.Response.ContentType = ReturnExtension(Extension);
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + FileName);
byte[] buffer = (byte[])dtbl.Rows[0]["FileContent"];
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
else
{
context.Response.ContentType = "text/html";
context.Response.Write("<p>Need a valid id</p>");
}
}
catch (Exception ex)
{
context.Response.ContentType = "text/html";
context.Response.Write("<p>" + ex.ToString() + "</p>");
}
更新: 我最终得到的功能如下所列。 正如 Tim 提到的,DB.GetReposFileSize() 只是获取内容数据长度。 我在原始代码中调用此函数,而不是这两行:
byte[] buffer = (byte[])dtbl.Rows[0]["FileContent"];
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
新的下载功能:
private void GetFileInChunks(HttpContext context, int ID)
{
//string path = @"c:\somefile.txt";
//FileInfo file = new FileInfo(path);
int len = DB.GetReposFileSize(ID);
context.Response.AppendHeader("content-length", len.ToString());
context.Response.Buffer = false;
//Stream outStream = (Stream)context.Response.OutputStream;
SqlConnection conn = null;
string strSQL = "select FileContent from LM_FileUploads where ID=@ID";
try
{
DB.OpenDB(ref conn, DB.DatabaseConnection.PDM);
SqlCommand cmd = new SqlCommand(strSQL, conn);
cmd.Parameters.AddWithValue("@ID", ID);
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
reader.Read();
byte[] buffer = new byte[1024];
int bytes;
long offset = 0;
while ((bytes = (int)reader.GetBytes(0, offset, buffer, 0, buffer.Length)) > 0)
{
// TODO: do something with `bytes` bytes from `buffer`
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
offset += bytes;
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
DB.CloseDB(ref conn);
}
}
最佳答案
您可以使用DATALENGTH
获取 VARBINARY
的大小并使用 SqldataReader
对其进行流式传输,它是 Read
-或ReadBytes
-方法。
查看此答案以查看实现:Best way to stream files in ASP.NET
关于c# - 下载大文件,保存在数据库中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12140836/