当前位置:   article > 正文

vue3 前端大文件分片上传_vue3实现分片上传

vue3实现分片上传

1、大文件上传直接传的弊端?

大文件上传,当大文件上传时耗费时间长,有被中断的可能性,当被中断后,无论前面上传进度是多少,都会归0,无法实现断点续传

2、分片上传的好处?

分片上传:分片上传就是把要上传的大文件,按照某个大小进行切片,把切片文件逐一上传,在这里需要后端的配合,给前端分片上传和上传完合并的接口

3、分片上传原理?

分片上传把大文件变成了一个个的小文件上传,可以提升速度,如果中途中断,和后端配合设好唯一标识,下次上传同一个文件时根据文件本身的信息,例如文件名、文件大小等进行判断,如果新上传的文件和之前上传中断的文件是同一个文件时,可以从上传中断的分片继续上传,节约时间,从而实现断点续传

4、前端需要做的部分?

前端所需要做的工作是把文件进行分片,把分片逐一上传,并在最后一个切片上传完毕后请求后端进行文件合并

5、何时开始分片?

当选择完文件,拿到文件信息,就可以进行分片了

6、具体实现

html内容:

  1. <div class="uploader">
  2. <ul class="list">
  3. <li class="list__item" v-for="(item, index) in fileList" :key="item.url">
  4. <span>
  5. <i class="icon-icon-" />
  6. <span
  7. class="list__item-name"
  8. :title="item.name"
  9. >{{ interceptStr(item.name) }}
  10. </span>
  11. </span>
  12. <i class="icon-guanbi" @click="cancel({ item, index })" />
  13. </li>
  14. </ul>
  15. <p class="uploader__upload">
  16. <i class="icon-jiahao" /> 上传文件
  17. <input
  18. :accept=""
  19. type="file"
  20. class="uploader__input"
  21. @click="clearValue"
  22. @change="selectFile"
  23. />
  24. </p>
  25. </div>

js内容:

  1. //创建一个文件对象
  2. let files = {}
  3. //文件上传列表数据
  4. let fileArray=''
  5. //当前上传坐标
  6. let pareIndex = 0
  7. //请求接口所需参数
  8. let tempFile=''
  9. let tempFile=''
  10. let tempObject=''
  11. let id=''
  12. let modelUuid=''
  13. //上传文件列表
  14. const fileList = computed(() => {
  15. return Array.isArray(fileArray)
  16. ? fileArray
  17. : !fileArray
  18. ? []
  19. : [fileArray]
  20. })
  21. //清空inputvalue
  22. const clearValue = e => {
  23. e.target.value = ''
  24. }
  25. const selectFile = e =>{
  26. //获取所选文件信息
  27. files = e.target.files[0]
  28. //形成文件列表
  29. const { name } = files
  30. fileArray={name }
  31. //请求文件分片
  32. uploadFileSilce(files, pareIndex)
  33. }
  34. //请求合并文件
  35. const mergeFile=(pareTotal)=>{
  36. let params={
  37. folderName:tempFile,
  38. objectName:tempObject,
  39. partNum:pareTotal,
  40. stationModelId:id
  41. }
  42. //请求后端合并接口
  43. modelServe.mergeUpload(params).then(res => {})
  44. }
  45. //文件切片
  46. const uploadFileSilce = (file, pareIndex) => {
  47. // 文件名
  48. const { name } = file;
  49. //文件分片后,每一个分片的名字,按照坐标逐一递增
  50. let portFileName=file.name.substring(0,file.name.lastIndexOf("."))+'_'+`${pareIndex+1}`+file.name.substring(file.name.lastIndexOf("."))
  51. // 文件大小
  52. const { size } = file;
  53. // 分片大小(50M,可以自行设置)
  54. const pareSize = 1024 * 1024 * 50;
  55. // 分片总数
  56. const pareTotal = Math.ceil(size / pareSize);
  57. // 如果 当前分片索引 大于 总分片数
  58. if (pareIndex >= pareTotal) {
  59. // 合并文件
  60. mergeFile(pareTotal);
  61. return;
  62. }
  63. // 文件开始结束的位置
  64. const start = pareIndex * pareSize;
  65. const end = Math.min(start + pareSize, size);
  66. // 开始切割
  67. const packet = new File([file.slice(start, end)], portFileName)
  68. // 拼接请求参数
  69. const formData = new FormData();
  70. formData.append('files', packet);
  71. formData.append('partFileIndex', pareIndex+1)//当前分片下标
  72. formData.append('partFileSum', pareTotal)//总分片数
  73. formData.append('uuid', modelUuid)//文件uuid,(这里是跟后端获取的,根据自己需求修改)
  74. formData.append('filesName', portFileName)//分片文件名称
  75. formData.append('stationModelId', id)//id
  76. formData.append('fileSize', file.size)//大小这里是跟后端获取的,根据自己需求修改)
  77. // 如果 当前分片索引 小于 总分片数
  78. if (pareIndex < pareTotal) {
  79. //请求后端分片接口
  80. modelServe.portUpload(formData).then(res => {
  81. const { code, msg, data } = res.data
  82. if (code === 0) {
  83. pareIndex++;
  84. //准备合并所需要的参数
  85. tempFile=res.data.data.folderName
  86. tempObject=res.data.data.objectName
  87. // 递归调用 分片函数
  88. uploadFileSilce(file, pareIndex);
  89. }
  90. })
  91. }
  92. };

css内容:

  1. .uploader {
  2. width: 100%;
  3. &__upload {
  4. // background: #f2f3f5;
  5. // border-radius: 2px;
  6. border: 1px solid #e5e6eb;
  7. height: 0.161rem;
  8. min-height: 25px;
  9. width: 100%;
  10. position: relative;
  11. text-align: center;
  12. line-height: 0.161rem;
  13. color: #fff;
  14. width: 104px;
  15. height: 32px;
  16. background: #3491FA;
  17. border-radius:4px;
  18. opacity: 1;
  19. > input {
  20. position: absolute;
  21. opacity: 0;
  22. left: 0;
  23. right: 0;
  24. height: 100%;
  25. font-size: 0;
  26. cursor: pointer;
  27. }
  28. }
  29. &__input{
  30. color: #fff;
  31. width: 104px;
  32. height: 32px;
  33. background: #3491FA;
  34. border-radius: 4px 4px 4px 4px;
  35. opacity: 1;
  36. }
  37. }
  38. .list {
  39. display: flex;
  40. flex-direction: column;
  41. &__item {
  42. background: #e6effe;
  43. border-radius: 2px;
  44. height: 0.161rem;
  45. min-height: 25px;
  46. width: 100%;
  47. display: flex;
  48. align-items: center;
  49. justify-content: space-between;
  50. font-size: 14px;
  51. font-family: SourceHanSansCN-Regular, SourceHanSansCN;
  52. font-weight: 400;
  53. color: #165dff;
  54. margin-bottom: 10px;
  55. white-space: nowrap;
  56. padding: 0 0.056rem;
  57. &-name {
  58. margin-left: 0.056rem;
  59. cursor: pointer;
  60. }
  61. }
  62. .icon-guanbi {
  63. cursor: pointer;
  64. }
  65. }

感谢BreenCL博主的分享,感谢其他伙伴分享的大文件分片文章,学习到了许多,都写的很详细,如果大家有需要可以移步查看。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/66618
推荐阅读
相关标签
  

闽ICP备14008679号