vue大文件分片上传,vue-simple-uploader
这篇文章主要介绍了vue2中基于简单上传的文件分片上传组件,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
本文最主要参考的是这一篇,后端也是用框架来完成。
大文件上传(秒传/断点续传)_使用vue-简单上传程序插件- Vue/Django完整实现https://www.jb51.net/article/206178.htm
参考的代码地址:https://github。com/clear lighty/文件上传
简单上传文档:https://github。com/simple-Uploader/上传者
模板
div id=全局上传者
上传者
ref=上传者
:options=options
:autoStart=false
:file-status-text=statusText
@file-added=onFileAdded
@file-success=onFileSuccess
@file-progress=onFileProgress
@file-error=onFileError
@file-removed=onfileRemoved
class=上传程序-应用程序
上传者-不支持/上传者-不支持
!-文件拖拽上传区域-
上传者-丢弃id=全局上传者-丢弃
上传者-BTN id=全球上传者-BTN :attrs= attrs ref=上传BTN
div class= hzs-上传-图标
SVG视图框= 0 0 1024 1024 数据-图标=收件箱宽度= 1em 高度= 1em 填充=当前颜色
aria-hidden=true
focusable=false class=
小路
d=M885.2 446.3l-.2-。
/svg
/div
单击或拖动文件(.zip)到此区域以上传数据集/p
只支持单个文件,多次上传会被覆盖的
后者100元/人
/uploader-btn
/上传者-丢弃
!-文件列表-
上传者-列表
div class=文件面板插槽范围=道具
ul class= file-list ref= file list
李v-for=道具。文件列表中的文件:key=file.id
上传文件:class= file _ 文件。id ref= files :file= file :list= true /uploader-file
!- !格式化数据分区不重要的ndash-
!-div class= query _ check v-if= queryBtnShow -
!- button @click=queryCheck(uuid)校验查询/按钮-
!- !格式化数据分区输入类型= button v-on=查询检查(uuid) value=校/ndash;-
!- !ndashdiv v-if=queryCheckStatus 文件正在上传中/div ndash;-
!-span class= query check show v-if= query check show { check status } }/span-
!- /div -
!-div class= save-result v-if= saveBtnShow -
!- button @click=下载检查结果(文件路径)校验保存/按钮-
!- /div -
/李
v-if=! props.fileList.length
空的
/div
/ul
/div
/uploader-list
/上传者
/div
/模板
脚本
从"火花md5 "导入SparkMD5
从" @/config/defaultSettings "导入{接受文件配置}
从" @/api/uploadTool "导入{ checkResult,isFileExist,mergeFile,textCheck }
//从"商店"导入存储
//https://github . com/simple-Uploader/Uploader #事件
导出默认值{
data() {
返回{
选项:{
目标:"/api/upload/upload/",//目标上传统一资源定位器
测试块:真的,
块大小:“2048000”,
//chunkSize: 10240000 ,//分块时按该值来分
文件参数名称:“文件”,//上传文件时文件的参数名
maxChunkRetries: 3,//最大自动失败重试上传次数
//由于我自身业务原因,添加了校验查询功能,查询的时候不能控制
//对应上传文件的id,因此,去掉了多文件上传
//这里注释掉,就可以实现多文件上传了
//singleFile: true,//单文件上传
//上传分片前,会先向后端发送一个得到请求,该函数就是响应这个得到请求
checkChunkUploadedByResponse:function(chunk,message) {
console.log(上传分片前,会先向后端发送一个得到请求,该函数就是响应这个得到请求)
console.log(块)
console.log(消息)
设obj message=JSON。解析(消息)
console.log(objMessage:,objMessage)
//- 秒传说明-
//此处解开注释,配合后端传来的参数可以实现秒传,我因为上传后还需要进行校验请求,
//这里我就砍掉秒传功能了.
//-
//此处根据返回值来判断是否为秒传
//if(obj消息。跳过上传=== true ){
//返回真实的
//}
//根据返回的数组内容来判断哪些分片不需要重新上传
return (objMessage.uploaded []).indexOf(chunk.offset 1)=0
},
parseTimeRemaining:function(剩余时间,parsedTimeRemaining) {
返回剩余解析时间。替换(/\ s年?/,年)。替换(/\天?/,天)。替换(/\shours?/,小时)。替换(/\ s分钟?/,分钟)。替换(/\ s秒?/,秒)
}
},
属性:{
接受:接受文件配置。获取全部()
},
statusText: {
成功:"成功",
错误:"网络错误",
正在上传:"正在上传",
类型错误:"类型错误",
空错误:“空错误”,
暂停:"暂停",
等待:"等待",
cmd5:计算md5 ,
合并:"合并"
},
文件状态文本:(状态,响应)={
返回this . status text[状态]
},
saveBtnShow: false,
queryBtnShow:没错,
queryCheckShow: false,
//queryCheckStatus: false,
检查状态:"正在检查.",
uuid: ,
文件路径:""
}
},
已安装(){
//这个。$巴士在( openUploader ,query={
//this.params=query {}
//如果(这个. refs.uploadBtn) {
//文档。查询选择器( #全球上传者-BTN ).单击()
//}
//})
},
计算值:{
//上传者实例
上传者(){
归还这个. refs.uploader.uploader
}
},
方法:{
onFileAdded(文件,事件){
console.log(文件)
console.log(事件)
控制台。日志(这个。上传者。文件列表)
控制台。日志(这个。上传者。文件)
这个emit(canGoToNextStep ,false)
这个. emit(canGoToPreStep ,false)
//控制台。日志(这个。上传者。文件。长度)
//暂停文件上传
file.pause()
//
//这个。panel show=true
this.queryCheckShow=false
this.saveBtnShow=false
this.queryBtnShow=false
this.statusSet(file.id, md5 )
this.computedMD5(文件)
//setTimeout(()={
//this.computedMD5(文件)
//}, 5000)
//总线. emit(文件已添加);
//控制台。日志(这个。上传者。文件)
//控制台。日志(这个。上传者。文件。长度)
},
onFileProgress(根文件、文件、块){
console.log(
`正在上传${file.name},区块:${chunk.startByte /
1024 /
1024 } ~ $ { chunk。结束字节/1024/1024 } ` 1
)
},
async onFileSuccess(rootFile,File,response,chunk) {
console.log(onFileSuccess )
console.log(文件)
let res=JSON.parse(response)
file.success=true
//文件完成上传,文件合并的标志
if (res.needMerge===true) {
this.statusSet(file.id,"合并")
假设表单数据=新表单数据()
formData.append(filename ,file.name)
formData.append(标识符,参数[0])。唯一标识符)
formData.append(totalSize ,file.size)
formData.append(时间戳资源时间戳)
console.log(formData )
尝试{
//- 发送合并请求开始-
let RES=wait合并文件(formData)
//合并失败的处理
//if (res.code!==200) {
//这个. notification.error({
//消息:"错误",
//描述:检查时出现错误,请重试
//})
//file.cancel()
//返回
//}
//文件上传成功用户界面更新
this.statusRemove(file.id)
this.statusSet(file.id, success )
//this.queryBtnShow=true
//这个。$巴士$emit(文件成功)
//- 发送合并请求结束-
//- 发送请求询问是否校验成功开始-
//let formData2=new FormData()
//formData2.append(fpath ,res.filePath)
//formData2.append(fname ,res.fileName)
//let res2=await文本检查(表单数据2)
//if (res2.code!==200) {
//这个. notification.error({
//消息:"错误",
//描述:检查时出现错误,请重试
//})
//file.cancel()
//}
//this.uuid=res2.uuid
//这个。file _ path=res2。文件路径
//- 发送请求询问是否校验成功结束-
//this.statusRemove(file.id)
//this.statusSet(file.id,完成检查)
//收集文件相关数据
console.log(文件)
这个. store.commit(ADD_FILE_LIST ,FILE)
//提示可以到下一步了
这个. notification.success({
消息:"成功",
描述:"成功上传,转到下一步完成。"
})
这个emit(canGoToNextStep ,true)
这个. emit(canGoToPreStep ,true)
//file.uniqueIdentifier
//this.statusSet(file.id,正在检查);
//
////- 定时发送请求,看检验是否完成开始-
////定时发送请求,看检验是否完成
//let interval=setInterval(()={
//setTimeout(async ()={
//let formData3=new FormData()
//formData3.append(file_uuid ,res2.uuid)
//
//let res3=await检查结果(表单数据3)
//console.log(校验中,请稍等.)
//if (res3.code==200) {
//console.log(校验完成)
//clearInterval(间隔)
////这个。状态移除(文件。id);
////this.statusSet(file.id,检查成功);
//this.checkStatus=完成检查
//this.saveBtnShow=true
//}
//}, 0)
//}, 1000)
//
////- 定时发送请求,看检验是否完成结束-
} catch (e) {
这个. notification.error({
消息:"错误",
描述:"检查过程中出现错误,请重试"
})
file.cancel()
}
}
},
onFileError(根文件,文件,响应,块){
这个. notification.error({
消息:"错误",
描述:"请重试"
})
},
onfileRemoved(文件){
这个message.info(`${file.name}的上传已被取消`)
},
/**
* 计算上传文件的md5,实现断点续传和秒传
*/
computedMD5(文件){
让fileReader=新的fileReader()
假设时间=新日期()。getTime()
设blobSlice=
File.prototype.slice
File.prototype.mozSlice
File.prototype.webkitSlice
设currentChunk=0
const chunkSize=10 * 1024 * 1000
让组块=数学。ceil(文件。大小/块大小)
让spark=新SparkMD5 .ArrayBuffer()
//this.statusSet(file.id, md5 )
//$(.上传者-文件-动作)。css(显示,无);
loadNext()
fileReader.onload=e={
火花.附加(目标结果)
currentChunk
如果(当前块区){
//console.log(
//`第${currentChunk}分片解析完成,开始第${currentChunk
//1}/${chunks}分片解析`
//)
loadNext()
//实时展示讯息摘要5的计算进度
setTimeout(()={
文档。查询选择器(`。我的状态_ $ { file。id } `).text content= verify MD5 ((当前块)* 100).至固定值(0)"% "
//console.log(file.id)
//console.log(校验MD5 ((currentChunk/chunks) * 100).至固定值(0)"% ")
//控制台。日志(文档。查询选择器(`。我的状态_ $ { file。id } `))
//文档。查询选择器(`。我的状态_ $ { file。id } `).textContent=校验MD5 ((currentChunk/chunks) * 100).至固定值(0)"% "
}, 20)
}否则{
设md5=spark.end()
this.computeMD5Success(md5,文件)
spark.destroy() //释放缓存
console.log(
` MD5计算完毕:${file.name} \nMD5:${md5} \n分片:${chunks}大小:${
文件。大小
} 用时:$ {新日期()。getTime() - time}毫秒
)
}
}
fileReader.onerror=function() {
这个。错误(` 0文件${file.name}读取出错,请检查该文件`)
file.cancel()
}
函数loadNext() {
let start=当前块*块大小
let end=
start chunkSize=file.size?file.size : start chunkSize
文件阅读器。readasarraybuffer(blob切片。调用(文件。文件,开始,结束))
}
},
//计算讯息摘要5成功
异步计算d5成功(md5,文件){
file.uniqueIdentifier=md5 //将文件讯息摘要5赋值给文件唯一标识
this.statusRemove(file.id)
//file.resume()
console.log(computeMD5Success )
console.log(文件)
//把讯息摘要5校验结果传到后端检查是否存在这个文件
让那个=这个
尝试{
let res=await isFileExist({
md5,
文件名:文件。名称
})
如果(资源状态){
//文件未在s3存在的情况
if (res[is_exist]===false) {
这个。$确认({
标题:你确定要上传吗?,
内容:h=res.message,
确定文本:是,
onOk() {
//开始文件上传的一个动作
//将表单里的是否强制上传设置为错误的
file[is_force_process]=false
file.resume()
},
onCancel() {
那个. emit(canGoToPreStep ,true)
file.cancel()
}
})
}否则{
//是否需要强制上传
这个。$确认({
标题:文件已经存在,您确定要恢复吗?,
内容:h=res.message,
确定文本:是,
onOk() {
//开始文件上传的一个动作
//将表单里的是否强制上传设置为错误的
file[is_force_process]=true
file.resume()
},
onCancel() {
那个. emit(canGoToPreStep ,true)
file.cancel()
}
})
}
}否则{
file.cancel()
}
} catch (e) {
file.cancel()
}
},
//展示文件列表
//fileListShow() {
////let $ list=$( # global-uploader .文件列表)
//let $list=this .$refs.fileList
//
//if(list。是(:可见){
//$list.slideUp()
//}其他{
//$list.slideDown()
//}
//},
close() {
this.uploader.cancel()
},
/**
* 新增的自定义的状态: md5 、转码、失败
* @param id
* @param状态
*/
状态集(id,状态){
让状态映射={
md5: {
文本:"验证MD5”,
bgc: #fff
},
正在合并:{
文本:"合并",
bgc:"# e2eeff "
},
转码:{
文本:"代码转换",
bgc:"# e2eeff "
},
失败:{
文本:"上传失败",
bgc:"# e2eeff "
},
成功:{
文本:"成功上传",
bgc:"# e2eeff "
},
正在检查:{
文本:"正在检查",
bgc:"# e2eeff "
},
检查成功:{
文本:"检查正常",
bgc:"# e2eeff "
}
}
setTimeout(()={
设p=document.createElement(p )
p。class name=我的状态_ $ { id }
让父亲=文档。查询选择器(`。file _ $ { id }).上传者-文件-状态`)
p.setAttribute(style , position:absolute;top:-16px;左:0;右:0;底部:0;zIndex:1;背景色:$ {状态图[状态].bgc} `)
p。追加(状态图[状态])。正文)
父亲。阑尾孩子(p)
})
},
状态删除(id) {
//console.log(statusRemove )
//console.log(id)
这个. nextTick(()={
假设节点=文档。查询选择器(`。我的状态_ $ { id } `)
节点。父节点。移除子节点(节点)
})
},
错误(消息){
这个. notification.error({
消息:"错误",
描述:味精
})
},
//查询每个区块
查询检查:函数(uuid) {
console.log(uuid:,uuid)
console.log(文件路径:-,this.file路径)
//if (uuid===) {
//这个。querycheckstatus=true
//返回;
//}
假设表单数据=新表单数据()
formData.append(file_uuid ,uuid)
常数实例=这个.$http.post({
标题:{
"内容类型":"多部分/形式数据"
}
})
情况。帖子( http://127。0 .0 .1:8000/文件上传/检查结果,表单数据)。然后(res={
//console.log(点击了查询校验状态按钮);
if (res.data.code==200) {
//这个。querycheckstatus=false
this.checkStatus=检查正常
this.queryCheckShow=true
}否则{
this.checkStatus=正在检查.
this.queryCheckShow=true
}
})
},
//下载校验结果
下载_检查_结果(){
假设表单数据=新表单数据()
formData.append(文件路径,this.file路径)
常数实例=这个.$axios.create({
标题:{
"内容类型":"多部分/形式数据"
},
响应类型:“blob”
})
情况。帖子( http://127。0 .0 .1:8000/文件上传/文件下载,表单数据)。然后(响应={
如果(!响应){
返回
}
设url=window .URL.createObjectURL(新Blob([response.data])
让链接=文档。createelement( a )
link.style.display=none
link.href=url
link.setAttribute(下载, check-result.txt )
document.body.appendChild(链接)
link.click()
})
}
},
观察:{},
销毁(){
//这个。$巴士关闭( openUploader )
}
}
/脚本
样式范围语言=少
#全局上传者{
//位置:固定;
z指数:20;
最大宽度:1000像素;
边距:10px自动;
背景:# fff
箱形阴影:0 0 10px rgba(0,0,0,4);
//填充:10px
h2 {
填充:30px 0;
文本对齐:居中;
字体大小:20px
}。上传者-应用程序{
//宽度:880像素
//填充:15px
//margin:20px auto 0;
字体大小:14px
}
ul li {
列表样式类型:无;
}
李分部{
//left:-19px;
}
}。文件面板{
背景色:# fff
边框:1px纯色# e2e2e2
border-radius:7px 7px 0 0;
箱形阴影:0 0 10px rgba(0,0,0,0.2);文件标题{
显示器:flex
高度:40px
//行高:40px
填充:0 15px
边框-底部:1px纯色# DDD;操作{
flex:1;
文本对齐:右对齐;
}
}。文件列表{
位置:相对;
高度:240像素
溢出-x:隐藏;
溢出-y:自动;
背景色:# fff
//边框:1px纯黑;
填充:0;
> li {
background-color: #fff;
}
}
&.collapse {
.file-title {
background-color: #e7ecf2;
}
}
}
.no-file {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 16px;
}
.uploader-btn {
margin-right: 4px;
color: #fff;
padding: 6px 16px;
}
#global-uploader-btn {
//border: 1px solid #409eff;
//background: #409eff;
border: 0;
width: 100%;
//height: 100px;
padding: 15px;
color: #F5222D;
display: flex;
flex-direction: column;
align-items: center;
p {
padding: 0;
margin: 10px;
}
.hzs-upload-icon {
font-size: 40px;
}
.hzs-upload-title {
font-size: 20px;
}
.hzs-upload-description {
font-size: 16px;
color: rgba(0, 0, 0, 0.45)
}
}
#global-uploader-btn:hover {
background: none;
}
#global-uploader-drop {
//height: 150px;
padding: 0;
}
#global-uploader-drop:hover {
border: 1px dashed #F5222D;
}
#global-uploader-dir-btn {
border: 1px solid #67c23a;
background: #67c23a;
}
.save-result {
position: absolute;
margin-top: -24px;
margin-left: 700px;
z-index: 10;
}
.query_check {
position: absolute;
margin-left: 700px;
margin-top: -50px;
z-index: 10;
}
.queryCheckShow {
margin-left: 10px;
color: red;
font-size: 12px;
}
</style>
调用
<MyUploaderBox
@canGoToNextStep=canGoToNextStep
@canGoToPreStep=canGoToPreStep
></MyUploaderBox>
参考
vue实现分片上传 https://blog.csdn.net/AIfurture/article/details/103975897
字节跳动面试官:请你实现一个大文件上传和断点续传 https://juejin.cn/post/6844904046436843527
vue-simple-uploader组件的使用感受 https://www.jianshu.com/p/da8ad489095e
大文件上传(秒传/断点续传)_使用Vue-Simple-Uploader插件 --Vue/Django完整实现 https://blog.csdn.net/qq_36852780/article/details/107437875
相关代码和文档:
https://github.com/ClearlightY/FileUpload
https://github.com/shady-xia/Blog/tree/master/vue-simple-uploader
https://github.com/simple-uploader/Uploader
到此这篇关于vue2中基于vue-simple-upload的文件分片上传组件的文章就介绍到这了,更多相关vue-simple-upload文件分片上传内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。