1. 程式人生 > >C#實踐問題:如何實現檔案的上傳下載等

C#實踐問題:如何實現檔案的上傳下載等

一種學習的方法:把握住關鍵點、重點、難點、易錯點等,以點帶面。

使用C#編寫一個簡單的檔案上傳和下載功能很簡單,只要掌握了一些關鍵點和易錯點就足夠在很短的時間內設計一個實用的文件管理頁面。

 

檔案上傳

 

前端實現:

第一部分:在前臺aspx內嵌入一條上傳語句並給出一個button,不要忘記給外表單新增(runat=”server”),不然後臺是接收不到前臺傳入的資訊,程式碼如下:

<input id="upload" type="file" class="input-control" name="uploadfile" onkeydown="return false;" onmousedown="return false;"/>

<asp:Button ID="Button" class="btn" runat="server" Text="上傳" OnClick="btn_Upload_Click" />

注:這裡第一個控制元件是使用者選擇檔案,並提交的input,第二個用於觸發後臺click事件的button

 

後端實現:

第二部分:實現上傳功能,這裡我們分為兩類上傳:

第一種是IO二進位制流直接上傳到資料庫儲存,

第二種是以實體檔案形式儲存在伺服器內。

這兩種各有優劣,這裡就不一一贅述了。

 

以二進位制流的形式儲存在資料庫中:

這裡我們將使用(this.upload.PostedFile)這一方法來獲取我們所需的檔案資訊:

//這一段程式碼表示我們需要將傳入的IO進行一個篩選,如果是空或者超出了我們自定義的大小則報錯
 if (this.upload.PostedFile != null && this.upload.PostedFile.ContentLength >= 307200000)
      {
       //提示使用者檔案大於300M
      }
      else
      {
          upload();
      }

然後就是我們向資料庫傳輸IO流的過程了

//獲取檔名稱
    string name = this.upload.PostedFile.FileName; 
    string[] sArray = name.Split('\\');
    int n = sArray.Length;
    string filename = sArray[n-1];
//獲取檔案長度
    int uplength = this.upload.PostedFile.ContentLength+1;
//建立資料流物件   
    Stream sr = this.upload.PostedFile.InputStream;
//定義byte型陣列  
    byte[] IOStream = new byte[uplength];
//將資料放到b陣列物件例項中,其中0代表陣列指標的起始位置,uplength表示要讀取流的長度(指標的結束位置)   
    sr.Read(IOStream , 0, uplength);

//最後把IO流 IOStream 以SqlDbType.VarBinary的形式儲存入資料庫中
(注:在資料庫中儲存IOStream的列格式建議使用Image)

 

以建立檔案的形式儲存在伺服器端: 


這裡我們會推薦一種分塊上傳的方法,以便於上傳那些大檔案。

//獲取上載檔案大小
    int ContentLength = this.upload.PostedFile.ContentLength;
//定義分塊大小,每塊10M
    int bufferSize = 1024 * 1024 * 10;
//得到檔案總共分塊數
    int allnum = ContentLength / bufferSize + 1;
//開啟一個stream流用以讀取上傳檔案
    Stream stream = this.upload.PostedFile.InputStream;
    BinaryReader br = new BinaryReader(stream);
    for (int currentnum = 1; currentnum <= allnum; currentnum++)
    {
        if (currentnum == allnum) checkfile = true;
//每次讀取10M大小檔案
        byte[] fileByte = br.ReadBytes(bufferSize);
//呼叫介面上傳塊大小檔案二進位制流(fileByte),檔案的名稱(FileName),上傳檔案的路徑(addr),複查檔案模組(checkfile),長度(ContentLength)
        state = oDocMgt.UpLoadFileCumsumWrite(fileByte, FileName, addr, checkfile, ContentLength);
    }
//分塊上傳累加寫入檔案
 public string UpLoadFileCumsumWrite(byte[] data, string filename, string addr, bool checkfile, int Length)
 {
     string Str = "";
     try
     {
     //建立資料夾
         System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(addr);
         if (!dir.Exists) dir.Create();
     //檔案寫入
         FileStream fs = System.IO.File.Open(addr + filename, FileMode.Append);
         fs.Write(data, 0, data.Length);
         fs.Close();
         data = null;
     //讀取長度,並複查檔案長度是否一致
         if (checkfile)
         {
             int DataLength = System.IO.File.ReadAllBytes(addr + filename).Length;
             if (DataLength != Length) { Str = "False"; }
             else { Str = "OK"; }
         }
         return Str;
     }
     catch (Exception ex)
     {
         WriterTextLog(ex.ToString());
         DeleteFile(filename, addr);
         return ex.Message;
     }
 }
(注:如果報錯,一定不要忘記DeleteFile(filename, addr)這個錯誤的檔案)

 //刪除伺服器磁碟上指定檔案
   public string DeleteFile(string filename, string addr)
   {
       string path = addr + filename;
       if (System.IO.File.Exists(path))
       {
           System.IO.File.Delete(path);
       }
       return "";
   }
 

檔案下載


檔案下載分為單獨的檔案下載和多檔案打包下載

 

單獨的檔案下載: 


這裡展示從SQL取IO資料流的方式下載檔案,儲存在伺服器上的檔案下載方式就不列舉了,道理基本都是一樣的,讀取文字IO並傳輸到本地檔案就好了。

首先從資料庫獲取相應的列和資料:

byte[] dataByte = (byte[])ds.Tables[0].Rows[0][“DocData”]; 
string name = (String)ds.Tables[0].Rows[0][“DocName”]; 
int length = (int)ds.Tables[0].Rows[0][“DocSize”];

//寫入IO流實現下載方法
private void SingleFile(string name,int length,byte[] dataByte)
{
    try
    {
        //fstream.Write(dataByte, 0, length);   //二進位制轉換成檔案
        Response.AddHeader("Content-Disposition", "attachment; filename=\"" + HttpUtility.UrlEncode(name, System.Text.Encoding.UTF8) + "\"");
        Response.AddHeader("Content-Length", length.ToString());
        Response.BinaryWrite(dataByte);
        Response.Flush();
    }
    catch (Exception ex)
    {
        //丟擲異常資訊
    }
}

 

多檔案下載:


多個檔案下載的時候會涉及到壓縮打包,zip或者rar格式壓縮方法,zip只需要加入using zip 引用就可以實現,這裡我們使用rar壓縮:

第一步:建立一個臨時資料夾

//向臨時資料夾寫入檔案
public void FileSelect(byte[] dataByte, String name, int length)
{
    if (!Directory.Exists(DsSavePath_Temp))
    {
        Directory.CreateDirectory(DsSavePath_Temp);
    }
    FileStream fstream;
    if (File.Exists(DsSavePath_Temp + name))
    {
         fstream = File.Create(DsSavePath_Temp+ "("+i+")"+ name, length);
         i++;
    }else{
         fstream = File.Create(DsSavePath_Temp + name, length);
    }

    try
    {
        fstream.Write(dataByte, 0, length);   //二進位制轉換成檔案
    }
    catch (Exception ex)
    {
        //丟擲異常資訊
    }
    finally
    {
        fstream.Close();
    }

}
第二步:使用rar程式進行多個檔案壓縮打包

//壓縮寫入檔案以及資料夾
public string YaSuo(out bool bo, out TimeSpan times, string DocName)
{
 string rarurlPath = string.Empty;
 bo = false;
 //壓縮檔案
 string yasuoPathSave = DsSavePath_Temp + DocName;
 string yasuoPath = DsSavePath_Temp;
 System.Diagnostics.Process pro = new System.Diagnostics.Process();
 //WinRAR所在路徑
 pro.StartInfo.FileName = AppDomain.CurrentDomain.BaseDirectory+ @"WinRAR\WinRAR.exe";
 pro.StartInfo.Arguments = string.Format("a {0} {1} -r", yasuoPathSave, yasuoPath);

 pro.Start();
 times = pro.TotalProcessorTime;
 bo = pro.WaitForExit(60000);//設定一分鐘
 if (!bo)
     pro.Kill();
 pro.Close();
 pro.Dispose();
 rarurlPath = yasuoPathSave;
 return rarurlPath;
}

(注:一定要把rar資料夾的路徑寫正確,應為程式會呼叫WinRAR.exe進行檔案壓縮)

第三部:完成下載以後刪除我們之前使用的臨時資料夾和裡面的臨時檔案,只保留需要的已經完成的RAR壓縮包

// 刪除臨時資料夾
public void DelectTempFile(string adr)
{
    DsSavePath_Temp =  adr;
    DirectoryInfo dir = new DirectoryInfo(DsSavePath_Temp); 
    if (dir.Exists)
    {
        DirectoryInfo[] childs = dir.GetDirectories();
        foreach (DirectoryInfo child in childs)
        {
            child.Delete(true);
        }
        dir.Delete(true);
    }

最後,如果程式需要可以使用網頁下載方式進行檔案傳輸

protected void ResponseFile(string filename)
  {
      FileInfo file = new FileInfo(filename);//建立一個檔案物件
      Response.Clear();//清除所有快取區的內容
      Response.Charset = "GB2312";//定義輸出字符集
      Response.ContentEncoding = Encoding.Default;//輸出內容的編碼為預設編碼
      Response.AddHeader("Content-Disposition", "attachment;filename=" + file.Name);
      //新增頭資訊。為“檔案下載/另存為”指定預設檔名稱
      Response.AddHeader("Content-Length", file.Length.ToString());
      //新增標頭檔案,指定檔案的大小,讓瀏覽器顯示檔案下載的速度 
      Response.WriteFile(file.FullName);// 把檔案流傳送到客戶端
  }

Response.Clear();
Response.ClearHeaders();
Response.Buffer = true;
Response.ContentType = "application/octet-stream";
//傳入你的檔案路徑
ResponseFile(resultPath);
Response.Flush();
//結束關閉Response
Response.End();

結語:本文主要講述檔案的上傳下載的幾種常用的方法,按照邏輯和展示的程式碼,寫出自己的文件管理功能應該是沒有任何問題的。
--------------------- 

原文:https://blog.csdn.net/ddc201301/article/details/53906488