下载大文件,保存在数据库中 [英] Downloading large files, saved in Database
问题描述
我们有很多文件,在我们的SQL Server数据库中保存为二进制文件。
我已经将一个.ashx文件传递给用户。
不幸的是,当文件变得相当大时,它将失败,并出现以下错误:
We have a lot of files, saved as binary in our SQL Server database. I have made an .ashx file, that delivers these files, to the users. Unfortunately, when the files become rather large, it will fail, with the following error:
算术中溢出或下溢操作
Overflow or underflow in the arithmetic operation
我假设它的内存不足,因为我将二进制文件加载到一个字节[]。
I assume it runs out of memory, as I load the binary into a byte[].
所以,我的问题是,如何做这个功能,读取大块(也许?),当它是从数据库表?它也似乎是Response.TransmitFile()是一个很好的选择,但是再次,这将如何与数据库工作?
So, my question is, how can I make this functionality, read in chunks (maybe?), when it is from a database table? It also seems like Response.TransmitFile() is a good option, but again, how would this work with a database?
DB.GetReposFile(),在代码在下面,从数据库获取文件。有各种字段,条目为:
文件名,ContentType,datestamps和FileContent为varbinary。
The DB.GetReposFile(), in the code beneath, gets the file from the database. There are various fields, for the entry: Filename, ContentType, datestamps and the FileContent as varbinary.
这是我的功能,提供文件: / p>
This is my function, to deliver the file:
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>");
}
更新:
函数I结束了,是下面列出的。
DB.GetReposFileSize()只是获取内容Datalength,正如蒂姆提到的。
我在原始代码中调用这个函数,而不是这两行:
Update: The function I ended up with, is the one listed below. DB.GetReposFileSize() simply gets the content Datalength, as Tim mentions. I call this function, in the original code, instead of these two lines:
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
将其流式传输,它的 阅读
- 或 ReadBytes
-Method。
You can use DATALENGTH
to get the size of the VARBINARY
and stream it for instance with a SqldataReader
and it's Read
-or ReadBytes
-Method.
看看这个答案看看一个实现:在ASP.NET中流式传输文件的最佳方式
Have a look at this answer to see an implementation: Best way to stream files in ASP.NET
这篇关于下载大文件,保存在数据库中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!