java+vue分片上传,断点续传

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;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现Spring Boot和Vue.js的MinIO秒传和断点续传,您可以遵循以下步骤: 1. 创建一个Spring Boot项目并添加MinIO依赖: ``` <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.1.0</version> </dependency> ``` 2. 在您的Spring Boot应用程序中配置MinIO。您可以使用`MinioClient`类来进行这个操作。在配置文件中添加以下属性: ``` minio.accessKey=your-access-key minio.secretKey=your-secret-key minio.endpoint=your-minio-endpoint ``` 3. 在Vue.js中,您可以使用`axios`库来上传文件。以下是上传文件的示例代码: ``` <template> <div> <input type="file" v-on:change="uploadFile" /> </div> </template> <script> import axios from 'axios'; export default { methods: { async uploadFile(event) { const file = event.target.files[0]; const url = 'http://localhost:8080/uploadFile'; const data = new FormData(); data.append('file', file); try { const response = await axios.post(url, data, { headers: { 'Content-Type': 'multipart/form-data', }, }); console.log(response.data); } catch (error) { console.log(error); } }, }, }; </script> ``` 4. 在Spring Boot中,您可以创建一个REST API端点来处理文件上传请求。以下是一个示例代码: ``` @RestController public class FileUploadController { @Autowired private MinioClient minioClient; @PostMapping("/uploadFile") public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) throws Exception { String fileName = file.getOriginalFilename(); InputStream inputStream = file.getInputStream(); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType(file.getContentType()); metadata.setContentLength(file.getSize()); PutObjectOptions options = new PutObjectOptions(metadata); minioClient.putObject("my-bucket", fileName, inputStream, options); return ResponseEntity.ok("File uploaded successfully!"); } } ``` 5. 要实现MinIO的断点续传,您可以使用MinIO Java客户端库中提供的`MultiFileUploader`类。以下是一个示例代码: ``` @RestController public class FileUploadController { @Autowired private MinioClient minioClient; @PostMapping("/uploadFile") public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) throws Exception { String fileName = file.getOriginalFilename(); InputStream inputStream = file.getInputStream(); ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType(file.getContentType()); metadata.setContentLength(file.getSize()); PutObjectOptions options = new PutObjectOptions(metadata); MultiFileUploader uploader = new MultiFileUploader(minioClient, "my-bucket", fileName); uploader.setPartSize(5 * 1024 * 1024); // 5MB uploader.upload(inputStream, options); return ResponseEntity.ok("File uploaded successfully!"); } } ``` 以上是Spring Boot和Vue.js的MinIO秒传和断点续传的基本实现。您可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值