侧边栏壁纸
博主头像
分享你我博主等级

行动起来,活在当下

  • 累计撰写 107 篇文章
  • 累计创建 13 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

vue + element + .net core3.1实现文件分片上传

管理员
2020-12-17 / 0 评论 / 0 点赞 / 3 阅读 / 29519 字


el代码

      <el-upload
              class="upload-demo"
              ref="upload"
              drag
              action="void"
              :auto-upload="true"
              multiple
              :limit="1"
              :http-request="customUpload"
              :on-preview="handlePreview"
              :on-remove="handleRemove"
              :before-upload="beforeUpload"
              :before-remove="beforeRemove"
              :on-exceed="handleExceed"
              :file-list="fileList"
            >
              <i class="el-icon-upload"></i>
              <div class="el-upload__text">
                将文件拖到此处,或<em>点击上传</em>
              </div>
            </el-upload>
export default {
  data() {
    return {
      fileList: [],
    };
  },
  created: function() {
  },
  methods: {
    
    handleRemove(file, fileList) {
      console.log(file, fileList);
    },
    handlePreview(file) {
      console.log(file);
    },
    // eslint-disable-next-line no-unused-vars
    handleExceed(files, fileList) {
      this.$message.warning(`請在下方刪除已經有文件再上傳`);
    },
    beforeUpload(file) {
      if (type == 1) {
        if (
          !/\.(avi|wmv|mpg|mpeg|mov|rm|ram|swf|flv|mp4|wma|rmvb|mkv)$/.test(
            file.name
          )
        ) {
          this.$alert(
            "视频类型必须是.avi,wmv,mpg,mpeg,mov,rm,ram,swf,flv,mp4,wma,rmvb,mkv中的一种",
            "标题名称",
            {
              confirmButtonText: "确定",
              customClass: "mzindex"
            }
          );
          // alert(
          //   "视频类型必须是.avi,wmv,mpg,mpeg,mov,rm,ram,swf,flv,mp4,wma,rmvb,mkv中的一种"
          // );
          return false;
        }
      }
      if (type == 2) {
        if (!/\.(gif|jpg|jpeg|png|GIF|JPG|PNG|BMP)$/.test(file.name)) {
          alert("图片类型必须是.gif,jpeg,jpg,png,BMP中的一种");
          return false;
        }
      }
    },
    customUpload(file) {
      let vm = this;
      if (vm.formAdd.type == 1) {
        var urls = URL.createObjectURL(file.file);
        var audioElement = new Audio(urls);
        var duration;
        // eslint-disable-next-line no-unused-vars
        audioElement.addEventListener("loadedmetadata", function(_event) {
          duration = audioElement.duration; //时长为秒,小数,182.36
        });
      }
      let url = this.baseUrl + "v1/api/File/Upload";
      let createGuid = function() {
        function S4() {
          return (((1 + Math.random()) * 0x10000) | 0)
            .toString(16)
            .substring(1);
        }
        return (
          S4() +
          S4() +
          "-" +
          S4() +
          "-" +
          S4() +
          "-" +
          S4() +
          "-" +
          S4() +
          S4() +
          S4()
        );
      };
      this.fileUpload(url, file, 0, createGuid());
    },
    //上传文件
    fileUpload(uploadUrl, option, chunk, guid) {
      let vm = this;
      let file = option.file;
      //每次上传文件的大小
      let chunkSize = 1024 * 1024;
      //最大上传大小  默认100M
      let maxSize = 1024 * 1024 * 100;
      let maxChunk = Math.ceil(file.size / chunkSize);
      let formData = new FormData();
      //将文件进行分段
      let fileSize = file.size;
      if (fileSize > maxSize) {
        this.$message.error("文件大小不能超过" + maxSize / 1024 / 1024 + "M");
        return;
      }
      //当前上传进度
      let currentPercent = parseInt((chunk / maxChunk) * 100);
      option.onProgress({ percent: currentPercent }); //进度条
      formData.append(
        "file",
        file.slice(chunk * chunkSize, (chunk + 1) * chunkSize)
      );
      formData.append("name", file.name);
      formData.append("chunk", chunk);
      formData.append("maxChunk", maxChunk);
      formData.append("guid", guid);
      this.$request.postURL(uploadUrl, formData).then(resJson => {
        if (resJson.success) {
          if (!resJson.data.completed) {
            this.fileUpload(uploadUrl, option, ++chunk, guid);
          } else {
            console.log("上传成功", resJson);
            option.onSuccess(); //上传成功(打钩的小图标)
            vm.formAdd.name = resJson.fileName;
            vm.formAdd.url = resJson.path;
            vm.$message.success("文件上传成功");
            console.log("文件列表", vm.fileList);
          }
        } else {
          vm.$message.error(resJson.message);
        }
      });
    },
    // eslint-disable-next-line no-unused-vars
    beforeRemove(file, fileList) {
      // this.$confirm(`确定移除 ${file.name}?`, "提示", {
      //   distinguishCancelAndClose: true,
      //   lockScroll: false,
      //   modalAppendToBody: true
      // });
      return true;
    }
  }
};


后台上传代码

    [Route("[controller]")]
    [ApiController]
    public class FileController : ControllerBase
    {
      /// <summary>
        /// 文件存放的根路径
        /// </summary>
        private readonly string _baseUploadDir;
        public FileController(IWebHostEnvironment hostingEnvironment)
            {
                _baseUploadDir = Path.Combine(_hostingEnvironment.ContentRootPath, "files");
            }
                   /// <summary>
        /// 分片上传文件
        /// </summary>
        [HttpPost]
        [Route("upload")]
        public async Task<IActionResult> Upload()
        {
            try
            {
                FileUpload._baseUploadDir = _baseUploadDir;
                var fileName = Request.Form["name"];
                //当前分块序号
                var index = Request.Form["chunk"].ToString().ToInt();
                //所有块数
                var maxChunk = Request.Form["maxChunk"].ToString().ToInt();
                //前端传来的GUID号
                var guid = Request.Form["guid"];
                //临时保存分块的目录
                var dir = Path.Combine(_baseUploadDir, guid);
                //判断文件夹是否存在
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }
                //分块文件名为索引名,更严谨一些可以加上是否存在的判断,防止多线程时并发冲突
                var filePath = Path.Combine(dir, index.ToString());
                //表单中取得分块文件
                var file = Request.Form.Files["file"];
                //获取文件扩展名
                //var extension = file.FileName.Substring(file.FileName.LastIndexOf(".") + 1, (file.FileName.Length - file.FileName.LastIndexOf(".") - 1));
                var filePathWithFileName = string.Concat(filePath, fileName);
                using (var stream = new FileStream(filePathWithFileName, FileMode.Create))
                {
                    await file.CopyToAsync(stream);
                }
                bool completed = false;
                string saveName = string.Empty;
                string tempPath = string.Empty;
                //double duration = 0;
                //如果是最后一个分块, 则合并文件
                if (index == maxChunk)
                {
                    //获取文件格式
                    var fileFormat = Path.GetExtension(fileName);
                    //获取项目所在路径
                    string format = "";
                    if (fileFormat.ToUpper().IsIn(video))
                    {
                        format = "video";
                    }
                    if (fileFormat.ToUpper().IsIn(img))
                    {
                        format = "images";
                    }
                    var yearMonth = DateTime.Now.ToString("yyyyMMdd");
                    //最终保存路径
                    var finalDir = Path.Combine(_baseUploadDir, yearMonth);
                    finalDir = Path.Combine(finalDir, format);
                    tempPath = Path.Combine(yearMonth, format);
                    //判断文件夹是否存在
                    if (!Directory.Exists(finalDir))
                    {
                        Directory.CreateDirectory(finalDir);
                    }
                    //随机生成一个文件名
                    var trustedFileNameForFileStorage = Path.GetRandomFileName();
                    saveName = yearMonth + "_" + trustedFileNameForFileStorage + fileFormat;
                    var finalPath = Path.Combine(finalDir, saveName);
                    await MergeFileAsync(finalPath, guid);
                    //_logger.LogInformation("准备获取视频详情----" + finalPath);
                    //var mediaInfo = FFProbe.Analyse(finalPath);
                    //_logger.LogInformation("准备获取视频详情参数----" + mediaInfo.Duration.TotalSeconds);
                    //duration = mediaInfo.Duration.TotalSeconds;
                    completed = true;
                }
                return Created(nameof(FileController), new { success = true, path = Path.Combine("files", tempPath, saveName), fileName = fileName.ToString(), data = new { completed, name = fileName } });
            }
            catch (Exception ex)
            {
                _logger.LogError("上传出错", ex);
                throw ex;
            }
        }
        static string[] video = new string[] { ".MP4", ".AVI", ".WMV", ".MOV", ".MPEG" };
        static string[] img = new string[] { ".JPG", ".BMP", ".PNG" };
        /// <summary>
        /// 合并分片的文件
        /// </summary>
        /// <param name="fileName">文件名称</param>
        /// <param name="guid">文件guid</param>
        public static async Task MergeFileAsync(string fileName, string guid)
        {
            //临时文件夹
            var dir = Path.Combine(_baseUploadDir, guid);
            //获得下面的所有文件
            var files = Directory.GetFiles(dir);
            var finalPath = fileName;//Path.Combine(finalDir, saveName);
            using (var fs = new FileStream(finalPath, FileMode.Create))
            {
                //排一下序,保证从0-N Write
                var fileParts = files.OrderBy(x => x.Length).ThenBy(x => x);
                foreach (var part in fileParts)
                {
                    var bytes = await System.IO.File.ReadAllBytesAsync(part);
                    await fs.WriteAsync(bytes, 0, bytes.Length);
                    bytes = null;
                    //删除分块
                    System.IO.File.Delete(part);
                }
                await fs.FlushAsync();
                fs.Close();
                //删除临时文件夹和分片文件
                Directory.Delete(dir);
            }
        }
        
        
    }








0

评论区