When I try to find a solution for uploading large files in ASP.NET I’ve found a component met my requirement. It’s PowerUpload but this is not a free component. Fortunately, when I read the book ASP.NET 3.5 Unleashed I’ve found another solution in this book. Thank to Stephen Walther  and his solution. This solution apply for ASP.NET 2.0 and 3.5. I’ve also tried with ASP.NET 1.1 and it is ok.

Here’s the source code :

In the web.config you put the key httpRuntime and specify maxRequestLength up to 100 MB, requestLengthDiskThreshold is the buffer size for ASP.NET framework read each chunk of byte from uploaded file. Note that requestLengthDiskThreshold is not available with ASP.NET 1.1

For ASP.NET 2.0 and above :

<httpRuntime maxRequestLength=102400 requestLengthDiskThreshold=100/>

For ASP.NET 1.1 :

 <httpRuntime maxRequestLength=102400 />

 

Create an upload page :

WebForm1.aspx :

<%@ Page language=”c#” Codebehind=”WebForm1.aspx.cs” AutoEventWireup=”false” Inherits=”LargeFileUpload.WebForm1″ %>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN” >
<HTML>
 <HEAD>
  <title>WebForm1</title>
  <meta name=”GENERATOR” Content=”Microsoft Visual Studio .NET 7.1″>
  <meta name=”CODE_LANGUAGE” Content=”C#”>
  <meta name=”vs_defaultClientScript” content=”JavaScript”>
  <meta name=”vs_targetSchema” content=”http://schemas.microsoft.com/intellisense/ie5“>
 </HEAD>
 <body MS_POSITIONING=”GridLayout”>
  <form id=”Form1″ method=”post” runat=”server”>
   <INPUT type=”file” id=”fuAttachment” runat=”server”/>
   <br/>
   <asp:Button id=”btnSave” runat=”server”
    Text=”Save”></asp:Button>
   <br/>
   <asp:Repeater id=”rptListFiles” runat=”server”>
    <HeaderTemplate>
     <table border=”1″>
      <tr>
       <th>ID</th>       
       <th>File Name</th>
       <th>File Size (bytes)</th>
      </tr>
    </HeaderTemplate>
    <ItemTemplate>
     <tr>
      <td>
       <%#DataBinder.Eval(Container.DataItem,”Id”)%>
      </td>
      <td>
       <a href=’FileDownload.aspx?ID=<%#DataBinder.Eval(Container.DataItem,”Id”)%>&FileName=<%#DataBinder.Eval(Container.DataItem,”FileName”)%>’><%#DataBinder.Eval(Container.DataItem,”FileName”)%></a>
      </td>
      <td>
       <%#DataBinder.Eval(Container.DataItem,”FileSize”)%>
      </td>
     </tr>
    </ItemTemplate>
    <AlternatingItemTemplate>
     <tr>
      <td>
       <%#DataBinder.Eval(Container.DataItem,”Id”)%>
      </td>
      <td>
       <a href=’FileDownload.aspx?ID=<%#DataBinder.Eval(Container.DataItem,”Id”)%>&FileName=<%#DataBinder.Eval(Container.DataItem,”FileName”)%>’ target=”_blank”><%#DataBinder.Eval(Container.DataItem,”FileName”)%></a>
      </td>
      <td>
       <%#DataBinder.Eval(Container.DataItem,”FileSize”)%>
      </td>
     </tr>
    </AlternatingItemTemplate>
    <FooterTemplate>
     </table>
    </FooterTemplate>
   </asp:Repeater>
  </form>
 </body>
</HTML>

WebForm1.aspx.cs :

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.IO;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace LargeFileUpload
{
 /// <summary>
 /// Summary description for WebForm1.
 /// </summary>
 public class WebForm1 : System.Web.UI.Page
 {
  protected System.Web.UI.WebControls.Button btnSave;
  protected System.Web.UI.WebControls.Repeater rptListFiles;
  protected System.Web.UI.HtmlControls.HtmlInputFile fuAttachment;
  private string strConString;
 
  private void Page_Load(object sender, System.EventArgs e)
  {
   strConString = ConfigurationSettings.AppSettings["UnleashDBConnString"];

   if(!IsPostBack)
   {    
    LoadFileList();    
   }
  }

  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
   //
   InitializeComponent();
   base.OnInit(e);
  }
  
  /// <summary>
  /// Required method for Designer support – do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {   
   this.btnSave.Click += new System.EventHandler(this.btnSave_Click);
   this.Load += new System.EventHandler(this.Page_Load);

  }
  #endregion

  private void btnSave_Click(object sender, System.EventArgs e)
  {
   if (fuAttachment.PostedFile == null)
    return;
      
   SqlConnection con = new SqlConnection(strConString);
               
   using (con)
   {
    con.Open();
    int id = InsertFile(con, GetFileNameFromFullFileName(fuAttachment.PostedFile.FileName));
    if(id > 0)
     StoreFile(con, id, fuAttachment.PostedFile.InputStream);
   }

   LoadFileList();
  }

  private string GetFileNameFromFullFileName(string strFullFileName)
  {
   if(string.Empty.Equals(strFullFileName))
    return string.Empty;
   string strFileName = string.Empty;
   int iPos = strFullFileName.LastIndexOf(“\\”);
   if(iPos > -1)
    return strFullFileName.Substring(iPos + 1);
   return string.Empty;
  }

  private int InsertFile(SqlConnection con, string fileName)
  {
   // parse file name with asp.net 1.1
   
   string strInsertCommand = @”
                                    INSERT INTO Attachment(FileName) VALUES(@fileName)
                                    SELECT @id = SCOPE_IDENTITY()
                                   “;
   SqlCommand cmd = new SqlCommand();
       
   cmd.CommandText = strInsertCommand;
   cmd.Connection = con;

   cmd.Parameters.Add(new SqlParameter());
   cmd.Parameters.Add(new SqlParameter());
   
   cmd.Parameters[0].ParameterName = “@fileName”;
   cmd.Parameters[0].Size = 50;   
   cmd.Parameters[0].Value = fileName;

   cmd.Parameters[1].ParameterName = “@id”;
   cmd.Parameters[1].Size = 4;
   cmd.Parameters[1].Direction = ParameterDirection.Output;

   cmd.ExecuteNonQuery();
   if (cmd.Parameters[1].Value != DBNull.Value)
    return Convert.ToInt32(cmd.Parameters[1].Value);

   return 0;
  }

  private void StoreFile(SqlConnection con,int id, Stream byteStream)
  {
   int iBufferLength = 8040;
   // Step 1 update first byte stream
   string strUpdateCommandStep1 = @”UPDATE Attachment Set FileContent=@fileContent Where ID = @id”;
   SqlCommand cmdStep1 = new SqlCommand();

   cmdStep1.CommandText = strUpdateCommandStep1;
   cmdStep1.Connection = con;
       
   BinaryReader br = new BinaryReader(byteStream);

   byte[] buffer = br.ReadBytes(iBufferLength);

   bool isContinue = true;

   if (buffer != null)
   {
    cmdStep1.Parameters.Add(new SqlParameter());
    cmdStep1.Parameters.Add(new SqlParameter());

    cmdStep1.Parameters[0].ParameterName = “@fileContent”;
    cmdStep1.Parameters[0].Value = buffer;
    cmdStep1.Parameters[0].Size = iBufferLength;

    cmdStep1.Parameters[1].ParameterName = “@id”;
    cmdStep1.Parameters[1].SqlDbType = SqlDbType.Int;
    cmdStep1.Parameters[1].Size = 4;
    cmdStep1.Parameters[1].Value = id;

    cmdStep1.ExecuteNonQuery();
   }
   else
   {
    isContinue = false;
   }

   if (!isContinue)
    return;

   // Step 2 continue read from byte stream and update to database
   string strUpdateCommandStep2 = “UPDATE Attachment Set FileContent.Write(@buffer, null, 0) Where ID = @id “;
   SqlCommand cmdStep2 = new SqlCommand();
       
   cmdStep2.Connection = con;
   cmdStep2.CommandText = strUpdateCommandStep2;
   cmdStep2.Parameters.Add(new SqlParameter());
   cmdStep2.Parameters.Add(new SqlParameter());
       
   cmdStep2.Parameters[0].ParameterName = “@buffer”;
   cmdStep2.Parameters[0].SqlDbType = SqlDbType.VarBinary;
   cmdStep2.Parameters[0].Size = iBufferLength;

   cmdStep2.Parameters[1].ParameterName = “@id”;
   cmdStep2.Parameters[1].SqlDbType = SqlDbType.Int;
   cmdStep2.Parameters[1].Size = 4;
   cmdStep2.Parameters[1].Value = id;       

   buffer = br.ReadBytes(iBufferLength);
   while (buffer.Length > 0)
   {           
    cmdStep2.Parameters[0].Value = buffer;
           
    cmdStep2.ExecuteNonQuery();

    buffer = br.ReadBytes(iBufferLength);
   }

   br.Close();
  }   
  private void LoadFileList()
  {
   SqlConnection con = new SqlConnection(strConString);

   using(con)
   {
    SqlCommand cmd  = con.CreateCommand();
    cmd.CommandText = @”SELECT
          Id, FileName, FileContent, DATALENGTH(FileContent) As FileSize
         From Attachment”;         

    SqlDataAdapter da = new SqlDataAdapter(cmd);
    con.Open();
    DataTable dtb = new DataTable();
    da.Fill(dtb);

    if(dtb != null)
    {
     rptListFiles.DataSource = dtb;
     rptListFiles.DataBind();
    }
   }
  }
 }
}

 

FileDownLoad.aspx :

<%@ Page language=”c#” Codebehind=”FileDownload.aspx.cs” AutoEventWireup=”false” Inherits=”LargeFileUpload.FileDownload” %>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN” >

<html>
  <head>
    <title>FileDownload</title>
    <meta name=”GENERATOR” Content=”Microsoft Visual Studio .NET 7.1″>
    <meta name=”CODE_LANGUAGE” Content=”C#”>
    <meta name=vs_defaultClientScript content=”JavaScript”>
    <meta name=vs_targetSchema content=”http://schemas.microsoft.com/intellisense/ie5“>
  </head>
  <body MS_POSITIONING=”GridLayout”>
 
    <form id=”Form1″ method=”post” runat=”server”>

     </form>
 
  </body>
</html>

FileDownload.aspx.cs :

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.IO;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace LargeFileUpload
{
 /// <summary>
 /// Summary description for FileDownload.
 /// </summary>
 public class FileDownload : System.Web.UI.Page
 {
  private void Page_Load(object sender, System.EventArgs e)
  {
   if(!IsPostBack)
   {
    DownloadFile();
   }
  }

  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: This call is required by the ASP.NET Web Form Designer.
   //
   InitializeComponent();
   base.OnInit(e);
  }
  
  /// <summary>
  /// Required method for Designer support – do not modify
  /// the contents of this method with the code editor.
  /// </summary>
  private void InitializeComponent()
  {   
   this.Load += new System.EventHandler(this.Page_Load);
  }
  #endregion

  private void DownloadFile()
  {
   System.Web.HttpContext context = System.Web.HttpContext.Current;

   if (string.Empty.Equals((context.Request["ID"])))
    return;
   int id = Convert.ToInt32(context.Request["ID"]);

   if (string.Empty.Equals((context.Request["FileName"])))
    return;
   string strFileName = context.Request["FileName"];

   context.Response.Buffer = false;
   context.Response.AddHeader(“Content-disposition”, string.Format(“attachment; filename={0}”, strFileName));
   context.Response.ContentType = “application/octet-stream”;
       
   string strCommandText = “Select FileContent From Attachment Where Id = @id”;
   string strConnString = System.Configuration.ConfigurationSettings.AppSettings["UnleashDBConnString"];

   SqlConnection con = new SqlConnection(strConnString);
   SqlCommand cmd = new SqlCommand();
   cmd.CommandText = strCommandText;
   cmd.Connection = con;
       
   cmd.Parameters.Add(new SqlParameter());
   cmd.Parameters[0].ParameterName = “@id”;
   cmd.Parameters[0].SqlDbType = SqlDbType.Int;
   cmd.Parameters[0].Size = 4;
   cmd.Parameters[0].Value = id;

   using (con)
   {
    con.Open();
    SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);

    if (reader.Read())
    {                            
     int iBufferLength = 8040;
     byte[] chunk = new byte[iBufferLength];
     long iReturnCount = 0;
     long iStartIndex = 0;
     iReturnCount = reader.GetBytes(0, iStartIndex, chunk, 0, iBufferLength);

     while (iReturnCount == iBufferLength)
     {
      context.Response.BinaryWrite(chunk);
      iStartIndex += iBufferLength;

      iReturnCount = reader.GetBytes(0, iStartIndex, chunk, 0, iBufferLength);
     }
               
     // read remain byte from stream
     byte[] actualChunk = new byte[iReturnCount - 1];
     Array.Copy(chunk,0,actualChunk,0,(int)iReturnCount – 1);     
     context.Response.BinaryWrite(actualChunk);
    }                      
   }
  }
 }
}

 

The database use for this demo has one table Attachment :

Column Name

Data Type

Allow Nulls

Id

Int (identity)

 

FileName

Nvarchar(50)

 

FileContent

VarBinary(MAX)

yes