/// <summary> /// 合并文件 /// </summary> /// <returns></returns> public JsonResult MergeFiles(string md5, string filename) { try { //源数据文件夹 string sourcePath = getFileMD5Folder(); //合并后的文件路径 string targetFilePath = sourcePath + Path.GetExtension(filename); // 目标文件不存在,则需要合并 if (!System.IO.File.Exists(targetFilePath)) { if (!Directory.Exists(sourcePath)) { return(Json(JResult.Error("未找到对应的文件片"))); } MergeDiskFile(sourcePath, targetFilePath); } var vaild = VaildMergeFile(targetFilePath); if (!vaild.Result) { return(Json(vaild)); } DeleteFolder(sourcePath); FileUploadInfo fileResult = OwnBusiness(targetFilePath); return(Json(JResult.Success(fileResult))); } catch (Exception ex) { return(Json(JResult.Error(ex.Message))); } }
/// <summary> /// 校验合并后的文件 /// <para>1.是否没有漏掉块(chunk)</para> /// <para>2.检测文件大小是否跟客户端一样</para> /// <para>3.检查文件的MD5值是否一致</para> /// </summary> /// <param name="targetPath"></param> /// <returns></returns> private CommResult VaildMergeFile(string targetPath) { var clientFileName = Request.Form["filename"]; // 文件字节总数 var fileTotalSize = Convert.ToInt32(Request.Form["fileTotalSize"]); var targetFile = new FileInfo(targetPath); var streamTotalSize = targetFile.Length; try { if (streamTotalSize != fileTotalSize) { throw new Exception("[" + clientFileName + "]文件上传时发生损坏,请重新上传"); } // 对文件进行 MD5 唯一验证 var identifier = Request.Form["md5"]; var fileMd5 = GetMD5HashFromFile(targetPath); if (!fileMd5.Equals(identifier)) { throw new Exception("[" + clientFileName + "],文件MD5值不对等"); } return(JResult.Success()); } catch (Exception ex) { // 删除本地错误文件 System.IO.File.Delete(targetPath); return(JResult.Error(ex.Message)); } }
/// <summary> /// 文件分块上传 /// </summary> /// <param name="file">文件</param> /// <param name="chunk">当前分片在上传分片中的顺序(从0开始)</param> /// <returns></returns> public JsonResult ChunkUpload(HttpPostedFileBase file, int chunk = 0) { try { var md5Folder = getFileMD5Folder(); // 存在分片参数 if (Request.Form.AllKeys.Any(t => t == "chunk")) { var webAppUpNumsOfLoop = HMSUtil.GetConfig(EnuInitCode.WebAppUpNumsOfLoop.ToString()).ToInt(10); // 是10的倍数就休眠几秒(数据库设置的秒数) if (chunk % webAppUpNumsOfLoop == 0) { var webAppUpPauseTimesOfLoop = HMSUtil.GetConfig(EnuInitCode.WebAppUpPauseTimesOfLoop.ToString()).ToInt(10); Thread.Sleep(webAppUpPauseTimesOfLoop); } //建立临时传输文件夹 if (!Directory.Exists(md5Folder)) { Directory.CreateDirectory(md5Folder); } var chunkFilePath = md5Folder + "/" + chunk; if (file != null) { file.SaveAs(chunkFilePath); } else { byte[] byts = new byte[Request.InputStream.Length]; Request.InputStream.Read(byts, 0, byts.Length); var createChunkFile = System.IO.File.Create(chunkFilePath); createChunkFile.Write(byts, 0, byts.Length); createChunkFile.Close(); } var jsucess = JResult.Success(); jsucess.Code = chunk.ToStr(); // 当前片数等于总片数时,则返回切片完成的标识 var chunks = Request.Form["chunks"].ToInt(); if ((chunks - 1) == chunk) { jsucess.Message = "chunked"; } return(Json(jsucess, JsonRequestBehavior.AllowGet)); } else { //没有分片直接保存 string path = md5Folder + Path.GetExtension(file.FileName); file.SaveAs(path); return(Json(JResult.Success("chunked"))); } } catch (Exception ex) { return(Json(JResult.Error(ex.Message), JsonRequestBehavior.AllowGet)); } }
/// <summary> /// 校验合并后的文件 /// <para>1.是否没有漏掉块(chunk)</para> /// <para>2.检测文件大小是否跟客户端一样</para> /// <para>3.检查文件的MD5值是否一致</para> /// </summary> /// <param name="targetPath"></param> /// <returns></returns> private CommonResult VaildMergeFile(string targetPath) { var clientFileName = Request.Form["filename"]; // 文件字节总数 var fileTotalSize = Request.Form["fileTotalSize"]; var targetFile = new FileInfo(targetPath); var streamTotalSize = targetFile.Length; if (streamTotalSize != fileTotalSize) { // 删除本地错误文件 System.IO.File.Delete(targetPath); var errorResult = JResult.Error("[" + clientFileName + "]文件上传时发生损坏,请重新上传"); #region 记录日志 //BzfLogger.Log(new SysLog("切片上传-出错-数字档案编码:" + rentDoccode + " 数字档案详情编号: " + rentdoctbDetailId + " 错误信息见详情", // "WebAPP.Api.Flow.RentDocController", errorResult, // "请求路径:" + Request.Url.AbsolutePath)); #endregion return(errorResult); } // 3.判断上传完的最终的文件是否跟客户端大小一致,只是双保险 if (fileTotalSize != streamTotalSize) { var errorResult = JResult.Error("[" + clientFileName + "],文件大小跟上传文件的大小不匹配"); //HMSLogger.Log(new SysLog("合并-出错-文件大小不一致-见错误详情", "WebAPP.Api.Flow.RentDocController", // errorResult, "请求路径:" + Request.Url.AbsolutePath)); return(errorResult); } // 3.1 MD5对文件进行唯一验证 var identifier = Request.Form["md5"]; var fileMD5 = GetMD5HashFromFile(targetPath); if (!fileMD5.Equals(identifier)) { // 删除本地错误文件 System.IO.File.Delete(targetPath); var errMsg = "[" + clientFileName + "],文件MD5值不对等"; var errorResult = JResult.Error(errMsg); // BzfLogger.Log(new SysLog(errMsg, "WebAPP.Api.Flow.RentDocController", //errorResult, "请求路径:" + Request.Url.AbsolutePath)); return(errorResult); } return(JResult.Success()); }
public JsonResult GetMaxChunk(string md5, string ext) { try { var reult = JResult.Success(); // 检测文件夹是否存在,不存在则创建 var userPath = GetPath(); if (!Directory.Exists(userPath)) { DicCreate(userPath); } var md5Folder = getFileMD5Folder(); if (!Directory.Exists(md5Folder)) { DicCreate(md5Folder); return(Json(reult, JsonRequestBehavior.AllowGet)); } var fileName = md5 + "." + ext; string targetPath = Path.Combine(md5Folder, fileName); // 文件已经存在,则可能存在问题,直接删除,重新上传 if (System.IO.File.Exists(targetPath)) { System.IO.File.Delete(targetPath); return(Json(reult, JsonRequestBehavior.AllowGet)); } DirectoryInfo dicInfo = new DirectoryInfo(md5Folder); var files = dicInfo.GetFiles(); var chunk = files.Count(); if (chunk > 1) { //当文件上传中时,页面刷新,上传中断,这时最后一个保存的块的大小可能会有异常,所以这里直接删除最后一个块文件 reult.Data = (chunk - 1); return(Json(reult, JsonRequestBehavior.AllowGet)); } return(Json(reult, JsonRequestBehavior.AllowGet)); } catch (Exception ex) { var errMsg = ex.Message; return(Json(JResult.Error(errMsg), JsonRequestBehavior.AllowGet)); } }
/// <summary> /// 文件上传后调用自有业务 /// </summary> /// <param name="targetPath"></param> /// <returns>返回文件对象</returns> private CommResult OwnBusiness(string targetPath) { var fileResult = JResult.Success(); var filePath = _hostingEnvironment.ContentRootPath + "\\Files\\"; if (!Directory.Exists(filePath)) { DicCreate(filePath); } // 移动文件 var file = new FileInfo(targetPath); var newFilePath = filePath + Request.Form["filename"]; if (System.IO.File.Exists(newFilePath)) { System.IO.File.Delete(newFilePath); } file.MoveTo(newFilePath); return(fileResult); }
public JsonResult GetMaxChunk(string md5, string ext) { try { var result = JResult.Success(); // 检测文件夹是否存在,不存在则创建 var userPath = GetPath(); if (!Directory.Exists(userPath)) { DicCreate(userPath); } var md5Folder = GetFileMd5Folder(md5); if (!Directory.Exists(md5Folder)) { DicCreate(md5Folder); return(Json(result)); } var fileName = md5 + "." + ext; string targetPath = Path.Combine(md5Folder, fileName); // 文件已经存在,则可能存在问题,直接删除,重新上传 if (System.IO.File.Exists(targetPath)) { System.IO.File.Delete(targetPath); return(Json(result)); } var dicInfo = new DirectoryInfo(md5Folder); var files = dicInfo.GetFiles(); var chunk = files.Count(); if (chunk > 1) { #region 计算切片中途是否有缺失 /* var returnMax = 0; * var fileIntList = files.Select(x => Convert.ToInt32(x.Name)).OrderBy(x => x).ToList(); * if (fileIntList == null || fileIntList.Count == 0) * return Json(JResult.Success(), JsonRequestBehavior.AllowGet); * var maxFileInt = fileIntList.Max(); * var minFileInt = fileIntList.Min(); * if (minFileInt != 1) * return Json(JResult.Success()); * foreach (var item in fileIntList) * { * var nextFile = item + 1; * if (maxFileInt == nextFile) * { * returnMax = maxFileInt; * break; * } * if (!fileIntList.Where(x => x == nextFile).Any()) * { * returnMax = item; * break; * } * }*/ #endregion //当文件上传中时,页面刷新,上传中断,这时最后一个保存的块的大小可能会有异常,所以这里直接删除最后一个块文件 result.Data = (chunk - 1); return(Json(result)); } return(Json(result)); } catch (Exception ex) { var errMsg = ex.Message; return(Json(JResult.Error(errMsg))); } }
/// <summary> /// 文件分块上传 /// </summary> /// <param name="file">文件</param> /// <param name="md5">文件md5 值</param> /// <param name="chunk">当前分片在上传分片中的顺序(从0开始)</param> /// <param name="chunks">最大片数</param> /// <returns></returns> public async Task <JsonResult> ChunkUpload(IFormFile file, string md5, int?chunk, int chunks = 0) { try { var result = JResult.Success(); var md5Folder = GetFileMd5Folder(md5); var filePath = ""; // 要保存的文件路径 // 存在分片参数,并且,最大的片数大于1片时 if (chunk.HasValue && chunks > 1) { var uploadNumsOfLoop = 10; // 是10的倍数就休眠几秒(数据库设置的秒数) if (chunk % uploadNumsOfLoop == 0) { var timesOfLoop = 10; //休眠毫秒,可从数据库取值 Thread.Sleep(timesOfLoop); } //建立临时传输文件夹 if (!Directory.Exists(md5Folder)) { Directory.CreateDirectory(md5Folder); } filePath = md5Folder + "/" + chunk; result.Code = chunk.Value; if (chunks == chunk) { result.Message = "chunked"; } } else { var fileName = file?.FileName; if (string.IsNullOrEmpty(fileName)) { var fileNameQuery = Request.Query.FirstOrDefault(t => t.Key == "name"); fileName = fileNameQuery.Value.FirstOrDefault(); } //没有分片直接保存 filePath = md5Folder + Path.GetExtension(fileName); result.Message = "chunked"; } // 写入文件 using (var addFile = new FileStream(filePath, FileMode.OpenOrCreate)) { if (file != null) { await file.CopyToAsync(addFile); } else { await Request.Body.CopyToAsync(addFile); } } return(Json(result)); } catch (Exception ex) { return(Json(JResult.Error(ex.Message))); } }