1.分片上传 vue
//页面实现部分
<el-form-item label="宣传视频:" :label-width="formLabelWidth">
<template style="position: relative">
<el-button class="m_upload" type="primary" @click="uploadMp4">上传数据</el-button>
<el-upload
class="upload-demo"
ref="upload"
:headers="headers"
:action="action"
:http-request="function(){}"
:limit="2"
accept=".mp4"
:on-change="onChangeBuild"
:auto-upload="upload">
<el-button class = "btnUpload" ref = "upload1" style="display: none">上传数据</el-button>
</el-upload>
<el-progress :percentage=percentage :format="format"></el-progress>
<div v-show="showDiv" v-if="userForm.videoName">
<a class="el-upload-list__item-name"><i class="el-icon-document"></i> {{userForm.videoName}}
<a @click="deleteFile(userForm.updateUserId)" style="color: red">删除</a>
</a>
</div>
</template>
</el-form-item>
//文件上传按钮
<el-button type="primary" :disabled="checkBtn" @click="resume()">保存</el-button>
//以下是方法部分
percentage: any = 0
files: any = "";
resumeArr :any = [];
num = 0;
//断点续传
resume(){
this.checkBtn = true
let isJPG: boolean= true;
if(this.videoArray != null && this.videoArray.length>0){
this.videoArray.forEach((e: any) => {
this.files = e.raw
isJPG = e.raw.type === 'video/mp4';
});
if (!isJPG) {
this.$message.error('上传视频格式需为MP4!')
return ;
}
}
//查询后端多少分片上传
rtpUser.resume({ fileName: this.files.name }).then((res:any)=>{
if(res.resultCode == 0){
this.resumeArr = res.content
if(res.content != null){
this.num = res.content.length
}
this.uploadFileVideo();
}
})
}
//分片视频上传
uploadFileVideo(){
let size = this.files.size
let chunkSize = 10 * 1024 * 1024 // 1个分片 10M
let start = 0 // 上传的开始位置
let index = 0 // 分片索引, 从0开始(0,1,2...)
let totalFragmentCount = Math.ceil(size / chunkSize) // 总的分片数量
//当查询完分片数量和总的分片数量相等,直接发生请求合成文件
if(this.num == totalFragmentCount){
this.updateUserDialogOK()
this.videoArray = null
}else{
while (true) {
let end; // 当前分片的结束位置(不包括,开区间)
if (start + chunkSize > size) { // 如果加上了一个分片大小,超出了文件的大小, 那么结束位置就是文件大小
end = size
} else {
end = start + chunkSize // 如果加上了一个分片大小,没超出了文件的大小, 那么结束位置就是start加上分片大小
}
// 对file分片,分片完后, 给分片一个名字, 这个名字可以在后台获取为分片文件的真实名字
let sfile = new File([this.files.slice(start, end)],`${this.files.name}-${index}`)
//已经上传的分片不在进行上传
if(this.resumeArr == null ||!this.resumeArr.includes(index.toString())){
// 上传完这个分片后, 再走下面的代码
this.uploadFragmentFile(sfile, index, this.files.name, totalFragmentCount)
}
index++
if (end == size) { // 检查是否传完了, 传完了的话, 就跳出循环
this.percentage = 0
break
}
// 开始位置
start = end
}
}
}
// 上传分片文件(将切分的分片文件上传)
uploadFragmentFile(sfile:any, index :any, realFilename: any, totalFragmentCount:any) {
return new Promise((resolve:any) => {
let formData = new FormData()
formData.append('sFile', sfile)
formData.append('index', index)
formData.append('realFilename', realFilename)
rtpUser.updateVideo(formData).then((res: any)=>{
console.log(`上传第${index}个分片成功`,res);
if(res.resultCode = '0'){
resolve();
this.num ++
}
this.percentage = parseFloat(((this.num) / totalFragmentCount * 100).toFixed(1))
//当全部上传完成时,
console.log(this.num,totalFragmentCount)
if(this.num == totalFragmentCount){
this.updateUserDialogOK()
this.videoArray = null
}
});
})
}
// 修改用户信息-点击确定
async updateUserDialogOK() {
this.checkBtn = true
let form: any = new FormData();
if(this.files != null){
form.append("videoName",this.files.name);
}
let data = await rtpUser.updateUserUser(form);
if (data.resultCode == 0) {
(this as any).$message.success("文件上传成功");
this.showUpdateUserDialog = false;
this.percentage = 0;
this.files = null
this.pageRtpUser();
} else {
(this as any).$message.error(data.resultMsg);
}
this.checkBtn = false
}
//用于进度条显示 percentage 不能大于100 大于100后显示异常
format() {
return this.percentage === 100 ? '完成' : this.percentage +'%';
}
//方法调用
import { post } from '@iot/jit-iot-vue/core/plugins/axios'
const user = '/api/sysUser'
static async updateUserUser(form) {
return post(`${user}/mergeFragmentFile`, form)
}
//封装的请求
export function post(url, data = {}, params = {}) {
return _axios({
method: 'post',
url,
data,
params,
})
}
// eslint-disable-next-line
Plugin.install = function (Vue, options) {
// eslint-disable-next-line
Vue.axios = _axios
window.axios = _axios
Object.defineProperties(Vue.prototype, {
axios: {
get() {
return _axios
},
},
$axios: {
get() {
return _axios
},
},
})
}
if (!Vue.axios) {
Vue.use(Plugin)
}
java
//分片上传,上传流文件
public Map<String, Object> updateVideo(FragmentationVideoVo vo) {
//验证文件上传信息
verifyFileType(vo);
String md5 = DigestUtils.md5Hex(vo.getRealFilename());
try{
File dir = new File(getUploadFolder() + md5);
if (!dir.exists()) {
dir.mkdirs();
}
File sFileWithIndex = new File(getUploadFolder() + md5 + "/" + vo.getIndex());
vo.getSFile().transferTo(sFileWithIndex);
}catch (Exception e){
e.printStackTrace();
}
HashMap<String, Object> data = new HashMap<>();
data.put("data", md5);
return data;
}
/**
* 查询文件是否上传过,如果上传过,返回上传过的信息,为断点续传做准备
* @param json
*/
public List<String> resume(JSONObject json) {
List<String> list = new ArrayList<>();
String fileName = (String) json.get("fileName");
String md5 = DigestUtils.md5Hex(fileName);
File file = new File(getUploadFolder() + md5);
File[] files = file.listFiles();
if(files == null ){
return null;
}else{
for(int i=0;i<files.length;i++){
list.add(files[i].getName());
}
return list;
}
}
//文件全部上传完后,开始合并文件
public Map<String, Object> mergeFragmentFile(String realFilename) throws IOException {
System.out.println("-------开始合并文件");
// 合并的文件
RandomAccessFile raf = new RandomAccessFile(getUploadFolder() + realFilename, "rw");
// 获取分片所在文件夹
String md5 = DigestUtils.md5Hex(realFilename);
File file = new File(getUploadFolder() + md5);
File[] files = file.listFiles();
int num = files.length;
byte[] bytes = new byte[5 * 1024];
// 合并分片
for (int i = 0; i < num; i++) {
File iFile = new File(file, String.valueOf(i));
// 将每一个分片文件包装为缓冲流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(iFile));
int len = 0;
// 将分片文件包装的流写入RandomAccessFile
while ((len = bis.read(bytes)) != -1) {
raf.write(bytes, 0, len);
}
bis.close();
}
// 删除分片所在文件夹的分片文件
for (File tmpFile : files) {
tmpFile.delete();
}
// 删除分片所在文件夹
file.delete();
raf.close();
HashMap<String, Object> data = new HashMap<>();
data.put("path", getUploadFolder() + realFilename);
data.put("pathName",realFilename);
return data;
}