首页 > 其他分享 >大文件切片上传和断点续传

大文件切片上传和断点续传

时间:2023-09-23 15:00:38浏览次数:25  
标签:断点续传 const 文件 uploadedSize 切片 file 上传

大文件分片上传
前端知识点

md5加密算法用于确保信息传输完整一致
spark md5在散列大量数据(例如文件)时表现得更好。可以使用 FileReader 和 Blob 读取块中的文件,并将每个块附加到 md5

//创建一个spark md5计算arrayBuffer的对象 spark = new SparkMD5.ArrayBuffer()
// 添加到array buffer
spark.append(e.target.result);
//根据arrayBuffer内容生成最终哈希值
spark.end()

根据文件内容生成哈希文件名,这样即使上传的文件名不一样但是内容一样也不会重复上传。

nodejs知识点

fs 文件系统相关:
existsSync路径是否存在的同步版本
appendFileSync 将数据同步添加到文件(持续添加进去)
writeFileSync 同步的写入文件(只写入最后一次的)
readdirSyn 读取一个目录的文件,返回不包含.的文件名列表
path路径:
path.extname(path)文件后缀名
path.dirname(path)文件目录名
path.resolve() 把一个路径或路径片段的序列解析为一个绝对路径。
框架:
express.static()创建静态资源服务器 ,对外开放静态资源
express.use(模糊匹配)和express.all(精准匹配),
请求->中间件->相应

大文件切片上传过程
获取到文件dom,获取到file,以及file的类型,名字,大小以后可以使用new 一个spark MD5.ArrayBuffer,每次都将chunk,append到arraybuffer里,在最后一个分片传输时用spark.end()生成最终的hash文件名传给后端,然后使用file.slice对文件进行切片,需要保存已经上传的文件大小,分片大小,当上传的文件大小小于文件本身大小时循环切片上传。将文件大小,文件类型,文件名,已上传的文件大小和chunk文件通过formdata传给后端。
后端接收时检查是否存在这个文件,如果没有就是第一次上传,writefile创建文件,不然就直接appendfile。
涉及对路径的处理,将路径通过resolve保存为绝对路径,路径不写死而是通过dirname获取当前目录。

代码
前端

import {API,UPLOAD_INFO,ALLOWED_TYPE,CHUNK_SIZE} from './config.js'


;((doc)=>{
const oProgress=doc.querySelector("#uploadProgress")
const oUploder=doc.querySelector("#videoUploader")
const oInfo=doc.querySelector("#uploadInfo")
const oBtn=doc.querySelector("#uploadBtn")

//当前已经上传的文件大小
let uploadedSize=0

let uploadedResult=null

const init=()=>{
bindEvent()
}

function bindEvent(){
oBtn.addEventListener('click',uploadVideo,false)

}

async function uploadVideo(){
const {files:[file]}=oUploder
if(!file){
oInfo.innerText=UPLOAD_INFO['NO_FILE']
return
}

if(!ALLOWED_TYPE[file.type]){
oInfo.innerText=UPLOAD_INFO['INVAILD_TYPE']
return
}
const {name,size,type}=file
const fileName=new Date().getTime()+"_"+name
oProgress.max=size
oInfo.innerText=''

while(uploadedSize<size){
const fileChunk=file.slice(uploadedSize,uploadedSize+CHUNK_SIZE)
let formData=createFormData({name,type,size,fileName,uploadedSize,file: fileChunk})
try {
uploadedResult=await axios.post(API.UPLOAD_VIDED,formData)
} catch (error) {
oInfo.innerText=`${UPLOAD_INFO['UPLOAD_FAILED']} (${error.message})`
return
}
uploadedSize+=fileChunk.size
oProgress.value=uploadedSize
}
oInfo.innerText=`${file.name}+${UPLOAD_INFO['UPLOAD_SUCESS']}`
oUploder.value=null
createVideo(uploadedResult.data.video_url)
}

function createFormData({
name,
type,
size,
fileName,
uploadedSize,
file
}) {
const fd=new FormData()
fd.append('name',name)
fd.append('type',type)
fd.append('size',size)
fd.append('fileName',fileName)
fd.append('uploadedSize',uploadedSize)
fd.append('file',file)
return fd
}

function createVideo(src){
const oVideo = document.createElement('video')
oVideo.controls=true
oVideo.width='500'
oVideo.src=src
document.body.appendChild(oVideo)
}

init()
}
)(document);

后端

const express =require('express')
const bodyParser =require('body-parser')
const uploader=require('express-fileupload')
const {extname,resolve}=require('path')
const {existsSync,appendFileSync,writeFileSync}=require('fs')

const app = express()

const ALLOWED_TYPE={
'video/mp4':'mp4',
'video/ogg':'ogg'
}

app.use(bodyParser.urlencoded({extended:true}))
app.use(bodyParser.json())
app.use(uploader())
//静态文件对外开放
app.use('/',express.static('uploaded_temp'))

// 中间件
app.all('*',(req,res,next)=>{
res.header('Access-Control-Allow-origin','*')
res.header('Access-Control-Allow-Methods','POST,GET')
next()
})


const PORT=8080

// 监听post请求
app.post('/upload_video',(req,res)=>{
const { name,
type,
size,
fileName,
uploadedSize,
} =req.body
const {file}=req.files

if(!file){
res.send({
msg:'no file',
code:1001
})
return
}
if(!ALLOWED_TYPE[type]){
res.send({
msg:'type error',
code:1002
})
return
}
const _fileName=fileName+extname(name)
const filePath=resolve(__dirname,'./uploaded_temp/'+_fileName)

//如果已经上传文件大小不为0,说明已经上传过一部分了,文件存在,直接append
if(uploadedSize !='0'){
// 防止已经上传的被删除
if(!existsSync(filePath)){
res.send({
msg:'no file',
code:1003
})
return
}
appendFileSync(filePath,file.data)
res.send({
msg:'file appended',
code:0,
video_url:'http://localhost:8080/'+_fileName

})
return
}
// 说明第一次上传,所以创建文件
writeFileSync(filePath,file.data)
res.send({
msg:'file created',
code:0
})
})

// 启动web服务器,端口port
app.listen(PORT,()=>{
console.log('Server is running on'+PORT)
})

断点上传过程
上述过程需要修改,切片名称由文件hash和序号构成,后端文件会存放所有临时切片,如果最终全部切片上传完成,前端发送合并请求给后端,后端通过appendFileSync将所有切片合并,删除临时chunk。前端监听上传文件框的change事件,每次change就执行函数去生成hash文件名以及向后端发送请求获取该文件已经上传的切片列表。后端可以通过readdirsyn读取文件夹里保存的chunk返回给前端。前端在每次分片上传之前判断切片是否上传,不重复上传。后端在接收到合并请求后将切片排序并合并。

多文件上传
通过file添加multple同时上传多个文件,获取到dom的一个文件数组保存files,通过innerHtml添加到下面作为列表展示,同时添加移除功能,通过事件委托实现dom移除和files数组的移除,files数组实现删除需要对数组重构,每一个文件对象都有一个key属性,key通过随机数加日期生成。多文件发送ajax请求可以通过promise.all来处理,只要有一个上传失败就reject。

图片缩略图和视频预览
图片可以通过base64预览
视频可以通过合成切片以后后端express内置中间件的express.static返回预览

参考文章:http://blog.ncmem.com/wordpress/2023/09/23/%e5%a4%a7%e6%96%87%e4%bb%b6%e5%88%87%e7%89%87%e4%b8%8a%e4%bc%a0%e5%92%8c%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/

欢迎入群一起讨论

 

 

标签:断点续传,const,文件,uploadedSize,切片,file,上传
From: https://www.cnblogs.com/songsu/p/17724387.html

相关文章

  • 前端上传大文件处理(切片、断点续传)
    思路1.对文件做切片,即将一个请求拆分成多个请求,每个请求的时间就会缩短,且如果某个请求失败,只需要重新发送这一次请求即可,无需从头开始2.通知服务器合并切片,在上传完切片后,前端通知服务器做合并切片操作3.控制多个请求的并发量,防止多个请求同时发送,造成浏览器内存溢出,导致页......
  • 大文件断点续传、快传秒传实现方案
    前言为什么视频、音频、大型文档等大文件不能也直接上传吗,简单又方便?遇到手动暂停、网络中断、网络不稳定或者服务端响应超时,当你终于半天到99%,网络突然断开喜提从0%再来一次再者一次服务接受如此大的数据传输,不说服务器肯同意接收,即使配置同意接受这常常会使服务器出现响应超时......
  • 如何实现大文件断点续传、秒传
    大家先来了解一下几个概念:「文件分块」:将大文件拆分成小文件,将小文件上传\下载,最后再将小文件组装成大文件;「断点续传」:在文件分块的基础上,将每个小文件采用单独的线程进行上传\下载,如果碰到网络故障,可以从已经上传\下载的部分开始继续上传\下载未完成的部分,而没有必要从头开始......
  • 文件上传
    beforeUploadFile(file){    constformData=newFormData();    formData.append("files",file);    letparams={      data:formData    }    uploadFile(params).then(res=>{      if(r......
  • 前端大文件上传、文件切片、断点续传
    一、项目初始化1、项目初始化我们创建一个big-file-upload目录作为当前项目的根目录文件。执行以下命令对当前项目进行初始化,生成package.json文件:npminit-y2、搭建项目结构在项目根目录中创建public目录,作为前端静态资源目录。同时在public中创建index.html用于构......
  • 完整教程:使用SPRING BOOT实现大文件断点续传及文件校验
    一、简介随着互联网的快速发展,大文件的传输成为了互联网应用的重要组成部分。然而,由于网络不稳定等因素的影响,大文件的传输经常会出现中断的情况,这时需要重新传输,导致传输效率低下。为了解决这个问题,可以实现大文件的断点续传功能。断点续传功能可以在传输中断后继续传输,而不需......
  • 前端大文件分片上传断点续传
     分片上传分片上传是将大文件分成多个小文件进行上传,每个小文件的大小通常为1MB到10MB。上传时,将每个小文件分别上传到服务器,服务器再将这些小文件合并成一个完整的大文件。这种方法可以提高上传速度,减少上传失败的可能性。断点续传断点续传是指在上传过程中,如果上传失败或者......
  • 图片上传压缩处理
       解决用户上传图片后,按照用户规定的尺寸大小或者按照图片比例,对图片进行压缩。   自己试写的工具类,写的时候考虑了几个关键点:   1、图片格式   JAVA的API很好,com.sun.image.codec.jpeg.JPEGCodec和com.sun.image.codec.jpeg.JPEGImageEncoder这两个类基本上自......
  • JAVA应用XFire框架来实现WebServie的大文件传输功能之二(上传)
    xml文件:<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="http://xfire.codehaus.org/config/1.0"><service><name>HelloWorldService</name><namespace>http://localhost:8090......
  • Java大文件上传(秒传、分片上传、断点续传)
    一、秒传秒传就是不传,实现逻辑就是看数据库或者缓存里是否已经有这个文件了,有了,直接从已有的文件去拿就可以了(返回文件地址)。这里判断是否是相同文件,要用到信息摘要算法,详情可以参考:一文读懂当前常用的加密技术体系。信息摘要算法常常被用来保证信息的完整性,防止信息在传输过程中......