上传大文件首先要修改web.config文件,否则上传报错。在web.config添加如下配置maxRequestLength表示能上传的最大文件值,单位是KB,requestLengthDiskThreshold表示超过多少KB之后的文件缓存到文件系统,不缓存在内存,以减轻内存负担。requestLengthDiskThreshold必须小于maxRequestLength
<configuration> <system.web> <httpRuntime maxRequestLength ="1048576" requestLengthDiskThreshold ="100"/> </system.web> </configuration>
上传页面
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebFormLargeFile.aspx.cs" Inherits="WebApplication1.WebFormLargeFile" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <style type ="text/css" > .fileList { margin-bottom :5px; } </style> </head> <body> <form id="form1" runat="server"> <div> <asp:Label ID ="lblFile" runat ="server" AssociatedControlID ="upFile" Text ="World Document:"></asp:Label> <asp:FileUpload ID ="upFile" runat ="server" /> <asp:Button ID ="btnAdd" runat ="server" onclick="btnAdd_Click" Text ="上传" /> <hr /> <asp:Repeater ID ="rptFiles" runat ="server" DataSourceID ="srcFiles" > <HeaderTemplate > <ul class ="fileList"> </HeaderTemplate> <ItemTemplate > <li> <asp:HyperLink ID ="lnkFile" runat ="server" Text ='<%#Eval("FileName") %>' NavigateUrl ='<%#Eval("Id","~/FileHandlerLarge.ashx?Id={0}") %>'></asp:HyperLink> </li> </ItemTemplate> <FooterTemplate > </ul> </FooterTemplate> </asp:Repeater> </div> <asp:SqlDataSource ID="srcFiles" runat="server" ConnectionString="Data Source=localhost;Initial Catalog=test;Integrated Security=True" ProviderName ="System.Data.SqlClient" SelectCommand="SELECT * FROM [Files]"></asp:SqlDataSource> </form> </body> </html>
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.IO; using System.Data.SqlClient; using System.Data; namespace WebApplication1 { public partial class WebFormLargeFile : System.Web.UI.Page { const string connStr = "Data Source=localhost;Initial Catalog=test;Integrated Security=True"; protected void Page_Load(object sender, EventArgs e) { } protected void btnAdd_Click(object sender, EventArgs e) { if (upFile.HasFile) { if (CheckFileType(upFile.FileName)) { AddFile(upFile.FileName, upFile.FileContent); rptFiles.DataBind(); } } } private bool CheckFileType(string fileName) { return Path.GetExtension(fileName).ToLower() == ".doc"; } private void AddFile(string fileName,Stream upload) { using(SqlConnection conn=new SqlConnection(connStr)) { string sql = "insert into Files (FileName) values(@FileName) select @Id=SCOPE_IDENTITY() "; SqlCommand cmd = new SqlCommand(sql,conn); cmd.Parameters.AddWithValue("@FileName", fileName); SqlParameter IdParam= new SqlParameter("@Id", SqlDbType.Int); IdParam.Direction = ParameterDirection.Output; cmd.Parameters.Add(IdParam); conn.Open(); cmd.ExecuteNonQuery(); int id =Convert.ToInt32(IdParam.Value); StoreFile(id, conn, upload); } } private void StoreFile(int Id, SqlConnection conn, Stream upload) { int bufferLength = 8040; BinaryReader reader = new BinaryReader(upload);//从流中读取字节数据 byte[] chuk = new byte[bufferLength]; chuk = reader.ReadBytes(bufferLength); SqlCommand cmd =new SqlCommand("update Files set FileBytes=@FileBytes where Id =@id",conn); cmd.Parameters.AddWithValue("@id", Id); cmd.Parameters.Add("@FileBytes", SqlDbType.VarBinary, bufferLength).Value = chuk; cmd.ExecuteNonQuery(); //set 列名.write(表达式,@offset,@length)用表达式的值替换某列从开始索引@length长度字符 //set 列名.write(表达式,null,0)在某列末尾追加 //set 列名.write(表达式,0,null)从开始位置替换 //set 列名.write(null,@offset,@length)可以用来删除数据 //set 列名.write(表达式,@offset,@length)只能用于SQL Server2005以上 //set 列名.write(表达式,@offset,@length)用法参考https://www.debugease.com/mssqlbasic/1274092.html SqlCommand cmdAppend = new SqlCommand("update Files set FileBytes.Write(@FileBytes,null,0) where Id =@id", conn); cmdAppend.Parameters.AddWithValue("@id", Id); cmdAppend.Parameters.Add("FileBytes", SqlDbType.VarBinary, bufferLength); chuk = reader.ReadBytes(bufferLength); while (chuk.Length > 0) { cmdAppend.Parameters["FileBytes"].Value = chuk; cmdAppend.ExecuteNonQuery(); chuk = reader.ReadBytes(bufferLength); } reader.Close(); } } }
文件处理页面
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Data.SqlClient; using System.Data; namespace WebApplication1 { /// <summary> /// FileHandlerLarge 的摘要说明 /// </summary> public class FileHandlerLarge : IHttpHandler { const string connStr = "Data Source=localhost;Initial Catalog=test;Integrated Security=True"; public void ProcessRequest(HttpContext context) { context.Response.ContentType = "application/msword"; context.Response.Buffer = false; SqlConnection conn = new SqlConnection(connStr); SqlCommand cmd = new SqlCommand("select FileBytes from Files where Id =@Id", conn); cmd.Parameters.AddWithValue("@Id", context.Request["Id"]); using (conn) { conn.Open(); SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess); if (reader.Read()) { int bufferSize = 8040; byte[] chunk = new byte[bufferSize]; long retCount = 0; long startIndex = 0; //public override long GetBytes(int i, long dataIndex, byte[] buffer, int bufferIndex, int length) //从指定的列偏移量将字节流读入缓冲区,并将其作为从给定的缓冲区偏移量开始的数组。 retCount = reader.GetBytes(0, startIndex, chunk, 0, bufferSize); while (retCount == bufferSize) { context.Response.BinaryWrite(chunk); startIndex += bufferSize; retCount = reader.GetBytes(0, startIndex, chunk, 0, bufferSize); } //写入最后一个字节数组 byte[] actualChunk = new byte[retCount - 1]; Buffer.BlockCopy(chunk, 0, actualChunk, 0, (int)retCount - 1); context.Response.BinaryWrite(actualChunk); } } context.Response.Write("Hello World"); } public bool IsReusable { get { return false; } } } }