使用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)

以上就是IO流输入的方法,接下来我们将使用创建文件的形式保存在服务器端:
这里我们会推荐一种分块上传的方法,以便于上传那些大文件。

//获取上载文件大小
    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();



结语:本文主要讲述文件的上传下载的几种常用的方法,按照逻辑和展示的代码,写出自己的文档管理功能应该是没有任何问题的。

 

参考文章:http://blog.ncmem.com/wordpress/2023/12/07/c实现文件上传下载/