1、主要标签
<input type="file" id="upload_video_input" accept="video/*" hidden onChange={(e)=>this.changeUploadVideo(e)}/>
<video id="movie" style={{width:'100%',height:'100%'}} src={currentVideo} preload="auto" > </video>
注释:<input> 上传文件标签
<video> 上传的视频回显
currentVideo:全局变量,上传视频的地址
2、上传触发事件 onChange={(e)=>this.changeUploadVideo(e)}
const chunkIds //存储分片上传结果
changeUploadVideo = e =>{
const that = this
console.log(e.target.files)
const file = e.target.files[0]
const size = file.size // 上传文件的大小
const sizeM = file.size/1024/1024 // 单位是M兆 用于限制上传视频的大小
const name = file.name // 上传视频名称
// 获得 上传资源的时长
const url = URL.createObjectURL(file);
//经测试,发现audio也可获取视频的时长
const audioElement = new Audio(url);
let duration;
audioElement.addEventListener("loadedmetadata", function (_event) {
duration = audioElement.duration; // 上传视频的秒数
})
chunkIds =[] // 每次上传之前清空当前视频分片ids
this.synchroUpload(file,0) // 同步递归上传
//this.asynchronouslyUpload(file) // 异步上传
}
注意:如果需要做视频秒数满足限制才允许上传,那面需要注意上传监听事件的执行与上传方法的执行顺序
3.1、同步请求,通过递归调用分片上传----synchroUpload
// 同步分片上传 递归
synchroUpload = (file,number) =>{
const shardSize = 0.5 * 1024 * 1024 //以0.5MB为一个分片
const shardCount = Math.ceil(file.size / shardSize); //总片数
if(number<shardCount){
//计算每一片的起始与结束位置
const start = number* shardSize,
end = Math.min(file.size, start + shardSize);
//构造一个表单,FormData是HTML5新增的
const formData = new FormData();
formData.append("data", file.slice(start,end)); //slice方法用于切出文件的一部分
formData.append("name", file.name);
formData.append("total", shardCount); //总片数
const currentChunk = number+1;
formData.append("chunk",currentChunk); //当前是第几片
const url = "xxx/h5/upload/file_part"
axios.post(url,formData,{
header:{
"Content-Type":"multipart/form-data;name=chunk; boundary="+new Date().getTime()
}
}).then(res=>{
console.log("分片上传成功",currentChunk)
chunkIds.push(number)
this.synchroUpload(file,number+1) // 递归上传
},err=>{
console.log("失败分片",currentChunk)
return
})
}else{
if(chunkIds.length === shardCount){ // 所有分片上传完成
this.mergeVideo(file.name) // 合并分片
}
}
}
3.2、异步请求上传分片----asynchronouslyUpload
// 异步上传 分片上传
asynchronouslyUpload = (file) =>{
const shardSize = 0.5 * 1024 * 1024 //以4MB为一个分片
const shardCount = Math.ceil(file.size / shardSize); //总片数
for(var i=0;i<shardCount;++i){
//计算每一片的起始与结束位置
const start = i* shardSize,
end = Math.min(file.size, start + shardSize);
//构造一个表单,FormData是HTML5新增的
const formData = new FormData();
const startTime = new Date().getTime()
formData.append("data", file.slice(start,end)); //slice方法用于切出文件的一部分
formData.append("name", file.name);
formData.append("total", shardCount); //总片数
const currentChunk = i+1;
formData.append("chunk",currentChunk); //当前是第几片
const url = "xxx/h5/upload/file_part"
axios.post(url,formData,{
header:{
"Content-Type":"multipart/form-data;name=chunk; boundary="+new Date().getTime()
}
}).then(res=>{
chunkIds.push(i)
if(chunkIds.length === shardCount){
this.mergeVideo(file.name) // 合并分片
}
console.log("分片上传成功",currentChunk)
},err=>{
console.log("失败分片",currentChunk)
})
}
}
4、合并视频分片----mergeVideo
let currentVideo // 视频上传成功后的地址,video标签回显播放
// 合并视频
mergeVideo = (fileName) =>{
const url =`xxx/h5/upload/merge?fileName=${fileName}`
axios.post(url).then(res=>{
//video_url 接口约定返回的,完成视频的地址url
if(res.data.video_url && res.data.video_url !==""){
console.log(res.data.video_url)
currentVideo = res.data.video_url
}else{
console.log("合并视频失败")
}
},err=>{
console.log("合并视频失败")
})
}