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