下载大文件,保存在数据库中
我们有很多文件,在SQL Server数据库中保存为二进制文件。 我已经将用于传递这些文件的.ashx文件发送给用户。 不幸的是,当文件变得相当大时,它将失败,并出现以下错误:
算术运算中溢出或下溢
我假设它耗尽了内存,因为我将二进制文件加载到byte []中。
所以,我的问题是,当它来自数据库表时,我怎样才能创建这个function,读取块(也许?)? 似乎Response.TransmitFile()似乎是一个不错的选择,但同样,如何使用数据库?
DB.GetReposFile()在下面的代码中从数据库中获取文件。 条目有各种字段:Filename,ContentType,datestamps和FileContent as varbinary。
这是我的function,提供文件:
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("Need a valid id
"); } } catch (Exception ex) { context.Response.ContentType = "text/html"; context.Response.Write("" + ex.ToString() + "
"); }
更新:我最终得到的function是下面列出的function。 Tim提到,DB.GetReposFileSize()只获取内容Datalength。 我在原始代码中调用此函数,而不是这两行:
byte[] buffer = (byte[])dtbl.Rows[0]["FileContent"]; context.Response.OutputStream.Write(buffer, 0, buffer.Length);
新下载function:
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
-or ReadBytes
。
看看这个答案,看看实现: 在ASP.NET中流式传输文件的最佳方式