赞
踩
1、大文件上传直接传的弊端?
大文件上传,当大文件上传时耗费时间长,有被中断的可能性,当被中断后,无论前面上传进度是多少,都会归0,无法实现断点续传
2、分片上传的好处?
分片上传:分片上传就是把要上传的大文件,按照某个大小进行切片,把切片文件逐一上传,在这里需要后端的配合,给前端分片上传和上传完合并的接口
3、分片上传原理?
分片上传把大文件变成了一个个的小文件上传,可以提升速度,如果中途中断,和后端配合设好唯一标识,下次上传同一个文件时根据文件本身的信息,例如文件名、文件大小等进行判断,如果新上传的文件和之前上传中断的文件是同一个文件时,可以从上传中断的分片继续上传,节约时间,从而实现断点续传
4、前端需要做的部分?
前端所需要做的工作是把文件进行分片,把分片逐一上传,并在最后一个切片上传完毕后请求后端进行文件合并
5、何时开始分片?
当选择完文件,拿到文件信息,就可以进行分片了
6、具体实现
html内容:
- <div class="uploader">
- <ul class="list">
- <li class="list__item" v-for="(item, index) in fileList" :key="item.url">
- <span>
- <i class="icon-icon-" />
- <span
- class="list__item-name"
- :title="item.name"
- >{{ interceptStr(item.name) }}
- </span>
- </span>
- <i class="icon-guanbi" @click="cancel({ item, index })" />
- </li>
- </ul>
- <p class="uploader__upload">
- <i class="icon-jiahao" /> 上传文件
- <input
- :accept=""
- type="file"
- class="uploader__input"
- @click="clearValue"
- @change="selectFile"
- />
- </p>
- </div>
js内容:
- //创建一个文件对象
- let files = {}
- //文件上传列表数据
- let fileArray=''
- //当前上传坐标
- let pareIndex = 0
- //请求接口所需参数
- let tempFile=''
- let tempFile=''
- let tempObject=''
- let id=''
- let modelUuid=''
-
- //上传文件列表
- const fileList = computed(() => {
- return Array.isArray(fileArray)
- ? fileArray
- : !fileArray
- ? []
- : [fileArray]
- })
-
- //清空input的value
- const clearValue = e => {
- e.target.value = ''
- }
- const selectFile = e =>{
- //获取所选文件信息
- files = e.target.files[0]
- //形成文件列表
- const { name } = files
- fileArray={name }
- //请求文件分片
- uploadFileSilce(files, pareIndex)
- }
- //请求合并文件
- const mergeFile=(pareTotal)=>{
- let params={
- folderName:tempFile,
- objectName:tempObject,
- partNum:pareTotal,
- stationModelId:id
- }
- //请求后端合并接口
- modelServe.mergeUpload(params).then(res => {})
- }
- //文件切片
- const uploadFileSilce = (file, pareIndex) => {
- // 文件名
- const { name } = file;
- //文件分片后,每一个分片的名字,按照坐标逐一递增
- let portFileName=file.name.substring(0,file.name.lastIndexOf("."))+'_'+`${pareIndex+1}`+file.name.substring(file.name.lastIndexOf("."))
- // 文件大小
- const { size } = file;
- // 分片大小(50M,可以自行设置)
- const pareSize = 1024 * 1024 * 50;
- // 分片总数
- const pareTotal = Math.ceil(size / pareSize);
- // 如果 当前分片索引 大于 总分片数
- if (pareIndex >= pareTotal) {
- // 合并文件
- mergeFile(pareTotal);
- return;
- }
- // 文件开始结束的位置
- const start = pareIndex * pareSize;
- const end = Math.min(start + pareSize, size);
- // 开始切割
- const packet = new File([file.slice(start, end)], portFileName)
- // 拼接请求参数
- const formData = new FormData();
- formData.append('files', packet);
- formData.append('partFileIndex', pareIndex+1)//当前分片下标
- formData.append('partFileSum', pareTotal)//总分片数
- formData.append('uuid', modelUuid)//文件uuid,(这里是跟后端获取的,根据自己需求修改)
- formData.append('filesName', portFileName)//分片文件名称
- formData.append('stationModelId', id)//id
- formData.append('fileSize', file.size)//大小这里是跟后端获取的,根据自己需求修改)
- // 如果 当前分片索引 小于 总分片数
- if (pareIndex < pareTotal) {
- //请求后端分片接口
- modelServe.portUpload(formData).then(res => {
- const { code, msg, data } = res.data
- if (code === 0) {
- pareIndex++;
- //准备合并所需要的参数
- tempFile=res.data.data.folderName
- tempObject=res.data.data.objectName
- // 递归调用 分片函数
- uploadFileSilce(file, pareIndex);
- }
- })
- }
- };
css内容:
- .uploader {
- width: 100%;
- &__upload {
- // background: #f2f3f5;
- // border-radius: 2px;
- border: 1px solid #e5e6eb;
- height: 0.161rem;
- min-height: 25px;
- width: 100%;
- position: relative;
- text-align: center;
- line-height: 0.161rem;
- color: #fff;
- width: 104px;
- height: 32px;
- background: #3491FA;
- border-radius:4px;
- opacity: 1;
-
- > input {
- position: absolute;
- opacity: 0;
- left: 0;
- right: 0;
- height: 100%;
- font-size: 0;
- cursor: pointer;
- }
- }
- &__input{
- color: #fff;
- width: 104px;
- height: 32px;
- background: #3491FA;
- border-radius: 4px 4px 4px 4px;
- opacity: 1;
- }
- }
- .list {
- display: flex;
- flex-direction: column;
- &__item {
- background: #e6effe;
- border-radius: 2px;
- height: 0.161rem;
- min-height: 25px;
- width: 100%;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-size: 14px;
- font-family: SourceHanSansCN-Regular, SourceHanSansCN;
- font-weight: 400;
- color: #165dff;
- margin-bottom: 10px;
- white-space: nowrap;
- padding: 0 0.056rem;
-
- &-name {
- margin-left: 0.056rem;
- cursor: pointer;
- }
- }
- .icon-guanbi {
- cursor: pointer;
- }
- }
感谢BreenCL博主的分享,感谢其他伙伴分享的大文件分片文章,学习到了许多,都写的很详细,如果大家有需要可以移步查看。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。