Win Form + ASP.NET Web Service 文件上传下载--HYAppFrame

 

本章节主要讲解HYAppFrame服务器端如何ASP.NET Web Service实现文件(含大文件)上传,WinForm客户端如何下载文件。

1    服务器端文件上传

1.1 上传文件

函数FileUpload(stringfileFullPath, byte[] file)用于上传文件,生成文件前检查文件路径所在文件夹是否存在,不存在则首先创建文件夹。

[WebMethod(EnableSession = true,Description = "上传文件")]
public int FileUpload(string fileFullPath,byte[] file)
{
   try
    {
       // 取得文件夹
       string dir = fileFullPath.Substring(0,fileFullPath.LastIndexOf("\\"));
       //如果不存在文件夹,就创建文件夹
       if (!Directory.Exists(dir))
           Directory.CreateDirectory(dir);
       // 写入文件
       File.WriteAllBytes(fileFullPath, file);
       return 1;
    }
   catch (Exception ex)
    {
       MyFuncLib.Log(ex.Message + "\r\n" + ex.StackTrace);
       return -1;
    }
}

1.2 合并文件

经过实验通过Web Service上传文件,如果大小超过2M可能遇到上传失败的错误,所以客户端处理上传大文件时,先分割成小文件,逐一上传,然后再到服务器上合并成原始文件。

[WebMethod(EnableSession = true,Description = "合并文件")]
public int FileMerge(string fileFullPath,int num)
{
   try
    {
       int i = 0;
       FileStream fs = new FileStream(fileFullPath, FileMode.Create,FileAccess.Write);
       while (num >= 0)
       {
           FileStream fsSource = new FileStream(fileFullPath + i, FileMode.Open,FileAccess.Read);
           Byte[] buffer = new Byte[fsSource.Length];
           fsSource.Read(buffer, 0, Convert.ToInt32(fsSource.Length));
           fs.Write(buffer, 0, buffer.Length);
           fsSource.Close();
           num--;
           i++;
       }
        fs.Close();
       // 删除临时文件
       while (i >= 0)
       {
           File.Delete(fileFullPath + i);
           i--;
       }
       return 1;
    }
   catch (Exception ex)
    {
       MyFuncLib.Log(ex.Message + "\r\n" + ex.StackTrace);
        return -1;
    }
}

1.3 删除文件

函数FileDelete(stringfileName)用于删除给定文件,删除前要检查用户是否通过身份验证,检查给定的文件路径是否包含特殊符号,例如,如果包含连续两个英文句号,使用者试图操作其他路径的文件。删除前,也要判断文件是否存在,删除后判断文件是否仍然存在,以此判断文件是否真正被删除。删除成功返回1,未删除任何文件返回0。

[WebMethod(EnableSession= true, Description = "删除指定文件")]
publicint FileDelete(string fileName)
{
    try
    {
        if (!IsLogin())
            return -100;
        fileName = MyFuncLib.WebDir +DES.Decrypt(fileName,MyFuncLib.passwordKey);
        // 不允许路径指向其他目录
        if (fileName.IndexOf("..")> -1)
            return 0;
        // 如果是文件夹,就跳过,不允许删除文件夹
        if (Directory.Exists(fileName))
            return 0;
        // 如果文件存在删除指定文件
        if (File.Exists(fileName))
            File.Delete(fileName);
        if (File.Exists(fileName))
            return 0;
        else
            return 1;
    }
    catch (Exception ex)
    {
        MyFuncLib.Log(ex.Message +"\r\n" + ex.StackTrace);
        return -1;
    }
}

2 客户端文件上传下载

2.1 文件上传

上传文件,支持多选,依次处理每一个文件。当待处理文件大小超过1M时,对其进行分割,并依次上传,当全部文件分割完毕后在服务器上合并。当文件上传后,需将文件的名称、存储路径、大小、类型、关联记录id等属性存入数据库。

privatevoid UploadFile()
{
    try
    {
        this.progressBarX1.Value = 0;
        this.progressBarX1.Minimum = 0;
        string dirName = SysParameters.WebDir +webDir;
        OpenFileDialog ofg = newOpenFileDialog();
        ofg.Title = "选择文件";
        ofg.Filter = "所有文件|*.*";
        ofg.FilterIndex = 1;
        ofg.RestoreDirectory = true;
        ofg.Multiselect = true;
        if (ofg.ShowDialog() ==DialogResult.OK)
        {
            this.warningBox1.Text =string.Empty;
            foreach (string fileName inofg.FileNames)
            {
                #region 逐一处理上传文件
                string newName =Guid.NewGuid().ToString() + MyFuncLib.getFileNameExt(fileName);
                using (FileStream fsSource =new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    // Read the source file into a bytearray.
                    long size =fsSource.Length;
                    if (size < int.MaxValue)
                       this.progressBarX1.Maximum = (int)size;
                    else
                        this.progressBarX1.Maximum = int.MaxValue - 1;
                    int unit = 1024000;
                    //如果文件体积小于1M,就一次性上传,如果文件大于1M就分割上传
                    if (size <= unit)
                    {
                        byte[] bytes = newbyte[size];
                        int numBytesToRead =(int)size;
                        int numBytesRead = 0;
                        while (numBytesToRead> 0)
                        {
                            // Read may returnanything from 0 to numBytesToRead.
                            int n =fsSource.Read(bytes, numBytesRead, numBytesToRead);
                            // Break when theend of the file is reached.
                            if (n == 0)
                                break;
                            numBytesRead += n;
                            numBytesToRead -=n;
                        }
                        numBytesToRead =bytes.Length;
                        MyFuncLib.WS.FileUpload(dirName + newName, bytes);
                        this.progressBarX1.Value =(int)size;
                    }
                    else
                    {
                        //倍数
                        int multiple =(int)(size / unit);
                        //余数
                        int residue = (int)(size - multiple* unit);
                        int i = 0;
                        while (multiple > 0)
                        {
                            byte[] bytes = newbyte[unit];
                            int numBytesToRead= (int)unit;
                            int numBytesRead =0;
                            while(numBytesToRead > 0)
                            {
                                // Read mayreturn anything from 0 to numBytesToRead.
                                int n =fsSource.Read(bytes, numBytesRead, numBytesToRead);
                                // Break whenthe end of the file is reached.
                                if (n == 0)
                                    break;
                                numBytesRead +=n;
                                numBytesToRead-= n;
                            }
                            numBytesToRead =bytes.Length;
                            MyFuncLib.WS.FileUpload(dirName + newName + i, bytes);
                            multiple--;
                            i++;
                            this.progressBarX1.Value = i * unit;
                        }
                        if (residue > 0)
                        {
                            byte[] bytes = newbyte[residue];
                            int numBytesToRead= (int)residue;
                            int numBytesRead =0;
                            while(numBytesToRead > 0)
                            {
                                // Read mayreturn anything from 0 to numBytesToRead.
                                int n =fsSource.Read(bytes, numBytesRead, numBytesToRead);
                                // Break whenthe end of the file is reached.
                                if (n == 0)
                                    break;
                                numBytesRead +=n;
                                numBytesToRead-= n;
                            }
                            numBytesToRead =bytes.Length;
                            MyFuncLib.WS.FileUpload(dirName + newName + i, bytes);
                        }
                        //在服务器上合并文件
                       MyFuncLib.WS.FileMerge(dirName + newName, i);
                    }
                    this.progressBarX1.Value =0;
                    //将成功上传的文件写入数据库
                    if (this.cateName == null)
                        this.cateName =string.Empty;
                    string sql = "insertinto core_attachment() values()";
                    ArrayList sqlParams = newArrayList();
                    ……
                    MyFuncLib.DBCommandExecNoneQueryBySql(sql, sqlParams);
                    this.warningBox1.Text ="“" + fileName + "”文件已上传";
                }
                #endregion
            }
        }
    }
    catch (Exception ex) {
        MyFuncLib.logToDB("error","系统错误", ex.Message, ex.StackTrace);
        MyFuncLib.msg("选择文件遇到错误,"+ ex.Message,"e");
    }
}

2.2 文件下载

函数Download(string url, string path)用于下载文件。给定一个文件网址,下载文件并提供进度条支持。由于服务器端使用IIS架设,ASP.NET Web Service提供服务的同时,本身也是一个Web站点,所以可通过一个网址下载服务器上指定文件。为了保证服务器文件安全,有两个策略。首先设置IIS禁止列出文件目录,然后将上传到服务器的文件使用GUID重命名,由于GUID唯一性、无规律性,且比较复杂,所以服务器上的文件路径不容易被猜测,从而保证文件相对安全。

privateWebClient wc;
privatevoid Download(string url, string path)
{
    try
    {
        Uri uri = new Uri(url);

        wc = new WebClient();

        wc.Proxy = null;//设置上网代理为空

        wc.DownloadFileCompleted += newAsyncCompletedEventHandler(webClient_DownloadFileCompleted);

        wc.DownloadProgressChanged += newDownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);

        wc.DownloadFileAsync(uri, path);

        this.label1.Text = "正在下载文件“"+ oldName + "”";

    }
    catch (Exception ex) { MyFuncLib.msg("错误:连接服务器失败,"+ ex.Message, "e"); }
}

privatevoid webClient_DownloadProgressChanged(object sender,DownloadProgressChangedEventArgs e)

{
    this.progressBarX1.Value =e.ProgressPercentage;
}

privatevoid webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
    try
    {
    // 下载完成后打开指定文件
       System.Diagnostics.Process.Start(appPath + oldName);
        this.Close();
    }
    catch (Exception ex) { MyFuncLib.msg("错误:打开文件失败,"+ ex.Message, "e"); }
}

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。