ทำอย่างไรให้เว็บไซต์ที่เราพัฒนาสามารถอัพโหลดไฟล์แบบคราวละหลายไฟล์ได้โดยไม่จำกัดจำนวน ด้วย ASP.NET(C#)

          ในการพัฒนาเว็บไซต์ บางครั้งอาจมีความจำเป็น หรือความต้องการจากผู้ใช้ที่ต้องการให้เว็บไซต์ดังกล่าวมีฟังก์ชั่นการทำงานในส่วนของการอัพโหลดไฟล์เพื่อแนบไฟล์เข้าไปในระบบและบันทึกลงฐานข้อมูล เพื่อให้สามารถเรียกดูข้อมูลการแนบไฟล์ดังกล่าวได้ในภายหลัง การอัพโหลดไฟล์จึงถือเป็นอีกหนึ่งฟังก์ชั่นการทำงานที่นักพัฒนาเว็บไซต์ควรทราบไว้ ซึ่งลักษณะการทำงานโดยทั่วไปส่วนใหญ่เราจะใช้ Control ที่มีเรียกว่า “FileUpload” แบบอัพโหลดครั้งละ 1 ไฟล์ และหากมีมากกว่านั้นก็จะมีการสร้างตัว FileUpload มาวางไว้ในหน้าจอเพิ่มตามจำนวนที่ต้องการแบบตายตัว เช่น หากในหน้าจอดังกล่าวต้องการสามารถให้ทำการอัพโหลดไฟล์ได้ไม่เกิน 5 ไฟล์ต่อการอัพโหลดแต่ละครั้งก็จะมีการลากคอนโทรล FileUpload มาวางไว้ในหน้าจอจำนวน 5 ตัว เพื่อให้สามารถรองรับความต้องการในการอัพโหลดไฟล์ของผู้ใช้ได้ แต่ผู้เขียนพบว่าการทำงานดังกล่าวอาจไม่รองรับความต้องการในการทำงานของผู้ใช้ที่จะเพิ่มไฟล์ได้ครั้งละหลายๆไฟล์โดยไม่จำกัดและผู้พัฒนาไม่จำเป็นต้องระบุหรือสร้างคอนโทรล FileUpload มาวางในหน้าจอในจำนวนที่ตายตัวโดยไม่จำเป็น โดยผู้ใช้สามารถคลิกปุ่มเพื่อเพิ่มจำนวนในการอัพโหลดไฟล์แต่ละครั้งได้เองเพื่อความยืดหยุ่นในการใช้งาน ในบทความนี้ ผู้เขียนจึงขอเสนอแนวทางในการพัฒนาเว็บไซต์โดยใช้ ASP.NET(C#) ในแบบที่มีการอัพโหลดไฟล์ได้คราวละหลายๆไฟล์ในแบบไม่ต้องจำกัดจำนวนคอนโทรล FileUpload ในหน้าจอโดยมีการระบุจำนวนไฟล์ที่สามารถอัพโหลดได้ในแต่ละครั้งโดยผู้พัฒนาแบบตายตัวอย่างเช่นที่กล่าวไว้ข้างต้น

          หลังจากที่ได้มีการศึกษาเพิ่มเติม ผู้เขียนพบว่าใน .NET Framework เวอร์ชั่น 4.5 นั้นจะมีการเพิ่ม Feature การทำงานในส่วนนี้ให้กับคอนโทรล FileUpload ไว้แล้วผ่าน Properties ที่เรียกว่า AllowMultiple ซึ่งจะทำให้สะดวกต่อการพัฒนาและสามารถลดปัญหาดังกล่าวข้างต้นได้ แต่สำหรับเวอร์ชั่นที่ต่ำกว่ายังคงต้องมีการปรับปรุงพัฒนาเพิ่มเติมเอง ในบทความนี้จึงขอยกตัวอย่างการพัฒนาทั้ง 2 แบบในเบื้องต้นโดยจะเน้นไปในแบบเวอร์ชั่นที่ต่ำกว่า 4.5 เพื่อให้ผู้อ่านได้นำไปเป็นแนวทางในการพัฒนาต่อไป ดังนี้
1. การอัพโหลดไฟล์คราวละหลายๆไฟล์โดยใช้ .Net Framework เวอร์ชั่นที่ต่ำกว่า 4.5

          ในบทความนี้ ผู้เขียนขอเสนอแนวทางแบบที่เป็นการพัฒนาโดยใช้จาวาสคริปต์เข้ามาเป็นตัวช่วยให้สามารถอัพโหลดไฟล์ได้ครั้งละหลายไฟล์ต่อการอัพโหลดแต่ละครั้ง เพื่อลดจำนวนการโหลดของหน้าจอและทำให้ผู้ใช้รู้สึกว่าการทำงานดังกล่าวเป็นไปด้วยความรวดเร็วไม่ต้องใช้เวลานาน โดยจะอธิบายทีละขั้นตอน ดังนี้

1) ออกแบบหน้าจอการทำงานในฝั่ง Client  ทำการออกแบบหน้าจอการทำงานไว้ในเบื้องต้น โดยมีการสร้างคอนโทรล FileUpload มาตั้งต้นไว้ 1 ตัว และมีปุ่มเพื่อให้ทำการเพิ่มคอนโทรล FileUpload ได้เองอัตโนมัติโดยตัวผู้ใช้เอง และปุ่มที่ใช้ในการอัพโหลดไฟล์จากคอนโทรล FileUpload ทั้งหมด ดังนี้

<body>
<form id="form1" runat="server">
<div>
 <div id="fileUploadarea" class="Divborder">
  <div id='divfirstUpload'><br /><asp:FileUpload ID="fuMultiple" runat="server" CssClass="fileUpload" onchange="javascipt:FileValidate(this,5);" />&nbsp;  <input style="display:inline;" id="BtnRemove" type="button" value="Remove" onclick="DelFileUpload('divfirstUpload');" /> 
</div> 
</div>
<br /> 
<div>&nbsp; 
<input style="display:inline; background-color: #A4EDFF; color: #333333; width: 150px; font-weight: bold;" id="btnAddMoreFiles" type="button" value="Add more files" onclick="AddMoreFilesWithMax(6);" />
&nbsp; <asp:Button ID="BtnUpload" runat="server" onclick="BtnUpload_Click" Text="Upload" OnClientClick="return ValidateFileUpload();" BackColor="#3399FF" Font-Bold="True" ForeColor="White" Width="150px" /> 
<br> 
<asp:GridView ID="gvResult" runat="server" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" Width="410px">
<RowStyle BackColor="#EFF3FB" /> 
<Columns> 
<asp:BoundField DataField="Name" HeaderText="ชื่อไฟล์"> 
<ItemStyle Width="200px" /> </asp:BoundField> 
<asp:BoundField DataField="FileSize" HeaderText="ขนาดไฟล์(KB)"> 
<ItemStyle HorizontalAlign="Right" Width="120px" /> 
</asp:BoundField> 
</Columns> 
<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> 
<PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" /> <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" /> <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" /> 
<EditRowStyle BackColor="#2461BF" /> <AlternatingRowStyle BackColor="White" /> 
</asp:GridView> 
</div> 
</div> 
</form> 
</body>

2) ในส่วนของจาวาสคริปต์ที่ใช้เป็นตัวช่วยในการตรวจสอบ โดยจะแยกเป็นแต่ละ function ดังนี้

2.1) ฟังก์ชั่นที่ใช้ในการเพิ่มไฟล์ได้ไม่จำกัด โดยใช้ชื่อว่า AddMoreFiles()

<script language="javascript" type="text/javascript">

function AddMoreFiles() {

  if (!document.getElementById && !document.createElement)
    return false;
////อ้างอิงถึง div ที่มีชื่อว่าfileUploadarea
  var fileUploadarea = document.getElementById("fileUploadarea"); 
  if (!fileUploadarea) return false; 
   var newLine = document.createElement("br"); fileUploadarea.appendChild(newLine); 
   var newFile = document.createElement("input"); 
   newFile.type = "file"; newFile.setAttribute("class", "fileUpload");

/////กำหนดค่าเริ่มต้นให้กับตัวแปร AddMoreFiles.lastAssignedId 
เพื่อใช้ในการกำหนด ID ให้กับคอนโทรลที่สร้างขึ้น และเป็นตัวนับ
  if (!AddMoreFiles.lastAssignedId) 
    AddMoreFiles.lastAssignedId = 1;

 //////กำหนดค่าแอททริบิวต์ต่างๆให้กับ FileUpload ที่ทำการสร้างใหม่ ในทีนี้คือ id และ name
    newFile.setAttribute("id", "FileUpload" + AddMoreFiles.lastAssignedId);  
    newFile.setAttribute("name", "FileUpload" + AddMoreFiles.lastAssignedId); 

 //////สร้าง div ขึ้นมาใหม่ และกำหนดค่าแอททริบิวต์ต่างๆให้กับ div ที่ทำการสร้างใหม่ 
ในทีนี้คือ id และ เพิ่มคอนโทรลที่สร้าง tag ไว้ด้านบนเข้ามาไว้ใน div 
    var div = document.createElement("div"); 
    div.appendChild(newFile); 
    div.setAttribute("id", "div" + AddMoreFiles.lastAssignedId); 

//////เพิ่ม div ที่สร้างใหม่ไปยัง div ที่มีชื่อว่า fileUploadarea และเพิ่มค่าของตัวแปร AddMoreFiles.lastAssignedId   
    fileUploadarea.appendChild(div); 
    AddMoreFiles.lastAssignedId++; 
}

2.2) ฟังก์ชั่นที่ใช้ในการเพิ่มไฟล์ได้โดยมีการระบุจำนวนสูงสุดที่ยอมให้อัพโหลดแต่ละครั้ง ในกรณีที่ต้องการระบุค่าจำนวนไฟล์ที่ต้องการให้ผู้ใช้สามารถอัพโหลดได้สูงสุดในแต่ละครั้ง สามารถปรับแก้เพิ่มเติมจากฟังก์ชั่นก่อนหน้านี้ โดยการส่งพารามิเตอร์จำนวนมากสุดที่ยอมให้สร้างตัวอัพโหลดไฟล์ได้ โดยใช้ชื่อฟังก์ชั่นว่า AddMoreFilesWithMax(x) ดังนี้

function AddMoreFilesWithMax(x) 
{ //////กำหนดค่าให้กับ AddMoreFiles.lastAssignedId 
เพื่อเป็นค่าตั้งต้นในการไปเซทค่า id และ name ของคอนโทรลที่สร้างใหม่ 
โดยในที่นี้เริ่มต้นที่ 2 เนื่องจากเดิมมีคอนโทรลอัพโหลดไฟล์อยู่เดิมแล้ว 1 ตัว
  if (!AddMoreFiles.lastAssignedId)
      AddMoreFiles.lastAssignedId = 2;

   if (!document.getElementById && !document.createElement)
      return false; 
  var fileUploadarea = document.getElementById("fileUploadarea");
    if (!fileUploadarea) return false;

/////เป็นการตรวจสอบเงื่อนไขว่ายังไม่เกินจำนวนมากสุดที่ระบุไว้ผ่านพารามิเตอร์ x
      if (AddMoreFiles.lastAssignedId <= x) 
      { 
      var newLine = document.createElement("br"); 

      //สร้างปุ่ม Remove เพื่อใช้ลบคอนโทรล FileUpload ที่สร้างขึ้นออกโดยผู้ใช้ 
      var newbtnDel = document.createElement("input"); 
      newbtnDel.setAttribute("id", "btnDelUpload" + AddMoreFiles.lastAssignedId);
      newbtnDel.setAttribute("name", "btnDelUpload" + AddMoreFiles.lastAssignedId); 
      newbtnDel.setAttribute("value", "Remove");   
      newbtnDel.type = "button"; 

     //////สร้างคอนโทรล FileUpload ขึ้นใหม่และกำหนดแอททริบิวต์ต่างๆให้
      var newFile = document.createElement("input"); 
      newFile.type = "file"; 
      newFile.setAttribute("class", "fileUpload");
      newFile.setAttribute("id", "FileUpload" + AddMoreFiles.lastAssignedId); 
      newFile.setAttribute("name", "FileUpload" + AddMoreFiles.lastAssignedId);

//////เป็นส่วนของการเรียกฟังก์ชั่นในการตรวจสอบไฟล์ที่ทำการอัพโหลดว่าถูกต้องตรงตามเงื่อนไขหรือไม่
     เมื่อมีการเลือกไฟล์ใดๆจากผู้ใช้ ซึ่งจะพูดถึงในส่วนถัดไปในการสร้างฟังก์ชั่น FileValidate(ctrl,maxVal) 
      newFile.setAttribute('onchange', 'javascipt:FileValidate(this,5);');

//////สร้าง div ขึ้นมาใหม่ และกำหนดค่าแอททริบิวต์ต่างๆให้กับ div ที่ทำการสร้างใหม่ 
ในทีนี้คือ id และ เพิ่มคอนโทรลที่สร้าง tag ไว้ด้านบนเข้ามาไว้ใน div 
      var div = document.createElement("div");
      div.appendChild(newLine);
      div.appendChild(newFile);
//////เพิ่มช่องว่างระหว่างคอนโทรลอัพโหลดไฟล์และปุ่ม Remove เพื่อความสวยงาม
      div.appendChild(document.createTextNode('\u00A0'));
      div.appendChild( newbtnDel);
      div.setAttribute("id", "div" + AddMoreFiles.lastAssignedId);

//////เพิ่ม event การคลิกปุ่ม Remove เพื่อให้ไปเรียกใช้ฟังก์ชั่น DelFileUpload
โดยส่งค่า id ของ div ที่ต้องการให้ลบออกซึ่งจะกล่าวถึงในส่วนถัดไปของการสร้างฟังก์ชั่น DelFileUpload(divid);
      newbtnDel.setAttribute('onclick', 'javascipt:DelFileUpload(\'' + "div" + AddMoreFiles.lastAssignedId + '\');');

      fileUploadarea.appendChild(div);
      AddMoreFiles.lastAssignedId++; } 

///////กรณีที่มีจำนวนตัวอัพโฟลดไฟล์ที่ถูกสร้างขึ้นเองเกินกว่าที่กำหนด(ค่าพารามิเตอร์ x) 
จะแสดงข้อความให้ทราบ
 else { 
       alert("ขออภัย ท่านสามารถอัพโหลดไฟล์ได้สูงสุดครั้งละไม่เกิน " + x + " ไฟล์ต่อการอัพโหลดแต่ละครั้ง กรุณาลองใหม่อีกครั้ง"); 
      return false;
       } 
      }

2.3) ฟังก์ชั่นที่ใช้ในการตรวจสอบขนาดของไฟล์ โดยมีการระบุขนาดสูงสุดที่ยอมให้อัพโหลดแต่ละครั้ง โดยใช้ชื่อฟังก์ชั่นว่า FileValidate(ctrlFile,MaxSize)

////เป็นการประกาศตัวแปรที่ใช้ในการตรวจสอบชนิดของไฟล์ที่ยอมให้อัพโหลดได้
var _validFileExtensions = [".jpg", ".jpeg", ".bmp", ".gif", ".png", ".pdf"];
function FileValidate(ctrlFile,MaxSize) 
{//////พารามิเตอร์ที่รับเข้ามาคือตัวคอนโทรลของการอัพโหลดไฟล์ที่ต้องการตรวจสอบ(ctrlFile) 
และขนาดสูงสุดของไฟล์ที่ยอมให้อัพโหลดในแต่ละคอนโทรล(MaxSize)

////ดึงค่าชื่อของไฟล์ที่อัพโหลดที่ต้องการตรวจสอบ
  var sFileName = ctrlFile.value;

/////ตรวจสอบเมื่อพบชื่อไฟล์ที่ดึง
   if (sFileName.length > 0) 
   { 
     var blnValid = false; 
//////////ตรวจสอบนามสกุลของไฟล์ที่ดึงมาจากชื่อไฟล์กับค่าของนามสกุลไฟล์ที่ยอมให้อัพโหลด
จากตัวแปร _validFileExtensions
     for (var j = 0; j < _validFileExtensions.length; j++) 
      { var sCurExtension = _validFileExtensions[j]; 
       if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) 
       { 
         blnValid = true; 
         break; 
        } 
      }   
//////กรณีไฟล์ดังกล่าวมีนามสกุลที่แตกต่างจากที่กำหนดจะแสดงข้อความแจ้งเตือน 
และล้างค่าของชื่อไฟล์ในคอนโทรลอัพโหลดไฟล์ตัวดังกล่าว
     if (!blnValid) 
     { alert("ไม่สามารถอัพโหลดไฟล์ดังกล่าวได้ เนื่องจากรองรับเฉพาะไฟล์ที่มีนามสกุลดังนี้เท่านั้น: " + _validFileExtensions.join(", ")); 
      ctrlFile.value = ""; 
      return false; 
     } 
     else 
     {
/////หากไฟล์ที่อัพโหลดมีนามสกุลไฟล์ตามที่ระบุ จะทำการตรวจสอบขนาดของไฟล์ว่าไม่เกินจากขนาดสูงสุด
ที่กำหนดหรือไม่ โดยมีการคำนวณหน่วยเป็น MB
       var fileSize = parseFloat(ctrlFile.files[0].size / 1048576).toFixed(2);

/////หากขนาดของไฟล์เกินกว่าที่กำหนดจะแสดงข้อความแจ้งเตือน และล้างค่าไฟล์ที่ต้องการอัพโหลด
ในคอนโทรลอัพโหลดไฟล์ดังกล่าว
       if (fileSize > MaxSize) 
        { alert(" ขออภัย ขนาดของไฟล์ที่ต้องการอัพโหลดมีขนาดใหญ่เกินกว่าทีกำหนด(" + MaxSize + " MB)"); 
          ctrlFile.value = ""; 
          return false;   
       } 
     }   
    }   
  return true; 
  }

2.4) ฟังก์ชั่นที่ใช้ในการตรวจสอบว่ามีการเลือกไฟล์ที่ต้องการอัพโหลดแล้วหรือไม่ เมื่อมีการกดปุ่ม “Upload” โดยใช้ชื่อฟังก์ชั่นว่า ValidateFileUpload() 

function ValidateFileUpload() { 
//////เป็นการค้นหาคอนโทรลไฟล์อัพโหลดที่มีในหน้าจอโดยใช้ tag input 
และตรวจสอบที่มี type เป็น "file" ใส่ไว้ในตัวแปร arrInputs
    var arrInputs = document.getElementsByTagName("input");
    var blnValid; 
    var oInput;
    for (var i = 0; i < arrInputs.length; i++)
     { oInput = arrInputs[i]; 
      if (oInput.type == "file") 
      { 
       var sFileName = oInput.value; 

 ///////หากพบตัวอัพโหลดไฟล์ตัวใดที่ยังไม่ได้ทำการเลือกไฟล์ไว้ จะทำการแสดงข้อความแจ้งเตือนให้ทราบ
       if (sFileName.length == 0) 
         { blnValid = false; 
          alert("ขออภัย ไม่สามารถอัพโหลดไฟล์ได้ เนื่องจากพบว่ามีบางไฟล์ไม่ได้ถูกเลือก กรุณาลองใหม่อีกครั้ง"); 
          return false;   
         } 
      }   
     }   
return true; 
}

2.5) ฟังก์ชั่นที่ใช้ในการลบคอนโทรลที่ใช้ในการอัพโหลดไฟล์ โดยใช้ชื่อฟังก์ชั่นว่า DelFileUpload(dv) ซึ่งจะส่งพารามิเตอร์เป็น id ของ div ตัวที่ต้องการให้ลบ และถูกเรียกใช้เมื่อมีการกดปุ่ม “Remove”

function DelFileUpload(dv) 
{ ////ค้นหา div ตาม id ที่ส่งเข้ามา
   var elem = document.getElementById(dv); 
  ///ทำการลบ div นั้นออกจากหน้าจอและลดค่าของ AddMoreFiles.lastAssignedId ลง 1
เพื่อใช้ในการคำนวณค่าสูงสุดและกำหนด tag ของ id และ name ของคอนโทรลที่สร้างใหม่ต่อไป
   elem.parentNode.removeChild(elem); 
   AddMoreFiles.lastAssignedId = AddMoreFiles.lastAssignedId - 1; 
}

3) ในฝั่งเซฺิร์ฟเวอร์ (C#)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
/////เป็น namespace ที่ต้องอ้างอิงเพิ่มเพื่อใช้ในการจัดการข้อมูลกับ datatable
using System.Data;
/////เป็น namespace ที่ต้องอ้างอิงเพิ่มเพื่อใช้ในการจัดการเกี่ยวกับการอัพโหลดไฟล์
using System.IO;
public partial class MultipleUpload : System.Web.UI.Page
{
protected void BtnUpload_Click(object sender, EventArgs e)
{
  try
  {

 //////สมมุติเพื่อนำไปประยุกต์ใช้กับการบันทึกลงฐานข้อมูลต่อไป 
โดยสร้างโครงสร้าง datatable ที่ชื่อว่า dtFiles 
     DataTable dtFiles = new DataTable();
     dtFiles.Columns.AddRange(new DataColumn[3] { new DataColumn("Id", typeof(int)),
     new DataColumn("Name", typeof(string)),
     new DataColumn("FileSize",typeof(string)) });

////เป็นการดึงคอนโทรลในการอัพโหลดไฟล์ที่ถูกสร้างขึ้นและวนรอบในการบันทึกไฟล์ดังกล่าว
 HttpFileCollection hfc = Request.Files;
 for (int i = 0; i < hfc.Count; i++)
 {
    HttpPostedFile hpf = hfc[i];
   if (hpf.ContentLength > 0)
    {
//////บันทึกไฟล์ตามที่ระบุไว้
    hpf.SaveAs(Server.MapPath("~/uploads/") + System.IO.Path.GetFileName(hpf.FileName));

////เพิ่มข้อมูลลงไปใน datatable ที่สร้างไว้ สำหรับการใช้งานจริงอาจเป็นการติดต่อเพื่อบันทึกลงฐานข้อมูล 
    dtFiles.Rows.Add(i,hpf.FileName, hpf.ContentLength / 1024);
     }
   }
 if (dtFiles.Rows.Count > 0) 
 {
//////ดึงข้อมูลจาก datatable มาแสดงในกริดวิว
    gvResult.DataSource = dtFiles;
    gvResult.DataBind();
 
 }
   }
  }
  catch (Exception)
  {
   throw;
   }
  }
}

เพิ่มเติม :
หากต้องการตกแต่งเพื่อความสวยงามสามารถใส่ StyleSheet เพิ่มเติมได้ ดังตัวอย่างต่อไปนี้

<style type="text/css">
  .fileUpload
  {
   width:255px;
   font-size:11px;
   color:#000000;
   border:solid;
   border-width:1px;
   border-color:#7f9db9;
   height:17px;
  }
 .Divborder
  {
   border: 2px solid;
   border-radius: 5px;
   padding:10px;
   width:390px;
  }
</style>

ตัวอย่างผลลัพธ์ที่ได้

1) แสดงหน้าจอ โดยแรกเริ่มมีอัพโหลดไฟล์ตั้งต้น 1 ตัว

uploadsingle

2) แสดงหน้าจอเมื่อมีการกดปุ่ม “Add more files” uploadmulti2

3) แสดงผลลัพธ์หลังจากบันทึกข้อมูลเรียบร้อยแล้วmultipleResult2

2. การอัพโหลดไฟล์คราวละหลายๆไฟล์โดยใช้ .Net Framework เวอร์ชั่น 4.5  ซึ่งในบทความนี้จะไม่ลงรายละเอียดมากนัก ผู้อ่านสามารถนำไปประยุกต์เพิ่มเติมได้ โดยจะอธิบายทีละขั้นตอนคร่าวๆ ดังนี้

1) การออกแบบในหน้าจอฝั่ง Client

<body>
<form id="form1" runat="server">
<div>
<asp:FileUpload ID="file_upload" runat="server" AllowMultiple="true" />
<asp:Button ID="btnFileUpload" runat="server" Text="Upload" OnClick="btnFileUpload_Click" />
<asp:Label ID="lblUploadStatus" runat="server"></asp:Label><br />
 <asp:GridView ID="gvResult" runat="server" AutoGenerateColumns="False" CellPadding="4" ForeColor="#333333" GridLines="None" Width="410px">
 <AlternatingRowStyle BackColor="White" />
 <Columns>
 <asp:BoundField DataField="Name" HeaderText="ชื่อไฟล์">
 <ItemStyle Width="300px" />
 </asp:BoundField>
 <asp:BoundField DataField="filesize" HeaderText="ขนาดไฟล์(KB)">
 <ItemStyle HorizontalAlign="Right" Width="110px" />
 </asp:BoundField>
 </Columns>
 <EditRowStyle BackColor="#2461BF" />
 <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
 <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
 <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />
 <RowStyle BackColor="#EFF3FB" />
 <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
 <SortedAscendingCellStyle BackColor="#F5F7FB" />
 <SortedAscendingHeaderStyle BackColor="#6D95E1" />
 <SortedDescendingCellStyle BackColor="#E9EBEF" />
 <SortedDescendingHeaderStyle BackColor="#4870BE" />
 </asp:GridView>
</div>
</form>
</body>

2) การพัฒนาในฝั่งเซิร์ฟเวอร์(C#)

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;
namespace WebAppTest
{
 public partial class MultipleUpload : System.Web.UI.Page
 {
 protected void btnFileUpload_Click(object sender, EventArgs e)
 {
 try
 {
///////การตรวจสอบขนาดไฟล์และไฟล์ต้องเป็นชนิด image/jpeg เท่านั้น
 if (file_upload.HasFile && file_upload.PostedFiles.All(x => x.ContentType == "image/jpeg" && x.ContentLength < 102400))
 {
///////ประกาศตัวแปร และกำหนดโครงสร้างของ datatable
 int i = 1;
 DataTable dtFiles = new DataTable();
 dtFiles.Columns.AddRange(new DataColumn[3] { new DataColumn("Id", typeof(int)),
 new DataColumn("Name", typeof(string)),
 new DataColumn("FileSize",typeof(string)) });
 foreach (var file in file_upload.PostedFiles)
 {
//////บันทึกไฟล์ที่เลือก
   file_upload.SaveAs(Server.MapPath("~/Fileupload/") + Path.GetFileName(file.FileName));
////วนบันทึกข้อมูลไฟล์ที่อัพโหลดลงใน datatable  
    dtFiles.Rows.Add(i, file.FileName, file.ContentLength / 1024);
 }

////แสดงข้อความเมื่อการอัพโหลดเสร็จสมบูรณ์
   lblUploadStatus.Text = "บันทึกสำเร็จ";

////แสดงค่าที่ได้ลงในกริดวิว
 if (dtFiles.Rows.Count > 0)
 {
 gvResult.DataSource = dtFiles;
 gvResult.DataBind();

 }
 }
 else
 {
////แสดงข้อความแจ้งเตือนกรณีเกิดปัญหาไฟล์มีขนาดใหญ๋เกินกว่าที่กำหนดและไม่ใช่ชนิด image/jpeg
   lblUploadStatus.Text = "กรุณาเลือกไฟล์ที่ต้องการอัพโหลดให้เหมาะสม";
 }
 }
 catch (Exception ex)
 {
////แสดงข้อความแจ้งเตือนกรณีเกิดปัญหาในการอัพโหลดไฟล์
   lblUploadStatus.Text = "เกิดข้อผิดพลาดในการอัพโหลดไฟล์ :" + ex.Message;
 }
 }
 }
}

ตัวอย่างผลลัพธ์ที่ได้

1) ก่อนทำการอัพโหลดไฟล์

multiple4_5_0

2) หลังอัพโหลดไฟล์ทั้งหมดเรียบร้อยแล้ว

multiple4_5

หมายเหตุ : หากกำหนดค่าให้กับ Properties ที่ชื่อว่า AllowMultiple=”false ตอนเลือกไฟล์ที่จะอัพโหลดจะสามารถเลือกได้เพียงไฟล์เดียวเท่านั้น

          จากบทความและตัวอย่างข้างต้น จะเห็นว่า ลักษณะผลลัพธ์ที่ได้จะคล้ายคลึงกัน แต่จะแตกต่างกันในส่วนของความซับซ้อนในการตรวจสอบความถูกต้องของข้อมูลไฟล์แนบที่รับเข้ามา ซึ่งผู้พัฒนาเองสามารถเลือกใช้วิธีที่ตนถนัดและขึ้นกับเวอร์ชั่นของ .NET Framework ที่กำลังพัฒนา รวมถึงเงื่อนไขของการตรวจสอบให้ตรงตามความต้องการของผู้ใช้มากที่สุด โดยเนื้อหาในบทความนี้เป็นเพียงแนวทางหนึ่งให้กับท่านในเบื้องต้นเท่านั้น ท่านสามารถนำไปประยุกต์ต่อยอดเพิ่มเติมได้ และผู้เขียนหวังเป็นอย่างยิ่งว่าบทความนี้จะเป็นประโยชน์กับผู้พัฒนาที่กำลังค้นหาวิธีการอัพโหลดไฟล์คราวละหลายไฟล์นี้อยู่เช่นกัน หากมีเนื้อหาส่วนใดผิดพลาด ผู้เขียนขออภัยไว้ ณ ที่นี้ด้วย ขอบคุณค่ะ ^^
แหล่งข้อมูลอ้างอิง :
http://www.aspsnippets.com/Articles/Uploading-Multiple-Files-using-JavaScript-Dynamic-FileUpload-Controls-in-ASP.Net.aspx
http://www.codeproject.com/Articles/667604/Upload-multiple-files-in-asp-net
http://www.c-sharpcorner.com/UploadFile/99bb20/upload-multiple-files-using-fileupload-control-in-Asp-Net-4/