首页 > 作文

java实现文件切片上传百度云+断点续传的方法

更新时间:2023-04-04 04:51:05 阅读: 评论:0

前言:

本文代码通过dubbo进行远程调用的接口,如果不使用dubbo,直接将rvice放到你的rvice,并稍作修改,redis替换成自己封装的工具即可。下方代码有点多,但基本上都加注释了。

切片上传百度云和上传到本地有所不同,上传到本地是需要前端给个唯一标识,通过自定义唯一标识保存到本地,最后在合并文件。而上传百度云则需要直接把切片传到百度云,唯一标识uploadid是百度云提供的,上传及合并都是直接调用百度云提供的接口。下方为百度云的使用文档。

对象存储bos – 文件管理 | 百度智能云文档 (baidu.com)

1.定义一个实体类

用于接收前台传过来的信息,信息应该包括总切片数,当前切片数,文件名称,文件总大小。

import com.geely.tcm.common.annotation.excel;import lombok.data; import javax.validation.constraints.max;import javax.validation.constraints.min;import javax.validation.constraints.notnull;import java.io.rializable;  @datapublic class mutilfileinfo implements rializable {    private static final long rialversionuid = 1l;     @notnull(message = "车型不能为空")    @excel(name = "车型")    private string model;     @excel(name = "文件名称")    private string name;     @excel(name = "文件总大小")    private long totalsize;     @min(value = 1, message = "不能小于1")    @max(value = 10000, message = "不能大于10000")    @excel(name = "当前分片序号")    private integer chunk;     @min(value = 1, message = "不能小于1")    @max(value = 10000, message = "不能大于10000")    @excel(name = "分片总数")    private integer chunks;}

2.创建controller

用于处理前端过来的文件及信息

import com.alibaba.fastjson.json;import com.baidubce.rvices.bos.model.partetag;import com.geely.tcm.common.annotation.log;import com.geely.tcm.common.bean.mutilfileinfo;import com.geely.tcm.common.bean.baidu.custompartetag;import com.geely.tcm.common.bean.measure.cmm3dmodel;import com.geely.tcm.common.configuration.redisutils;import com.geely.tcm.common.enums.businesstype;import com.geely.tcm.common.util.stringutils;import com.geely.tcom.remote.api.baidu.baiducloudbosrvice;import io.swagger.annotations.api;import io.swagger.annotations.apiimplicitparam;import io.swagger.annotations.apiimplicitparams;import io.swag行字开头成语ger.annotations.apioperation;import lombok.extern.slf4j.slf4j;import org.apache.dubbo.config.annotation.dubboreference;import org.springframework.web.bind.annotation.postmapping;import org.springframework.web.bind.annotation.requestmapping;import org.springframework.web.bind.annotation.requestparam;import org.springframework.web.bind.annotation.restcontroller;import org.springframework.web.multipart.multipartfile;import java.util.*;import java.util.concurrent.maphore;import java.util.stream.collectors;@api(tags = "文件上传下载服务")@requestmapping("/threemodel")@restcontroller@slf4jpublic class model3dcontroller1  {//dubboreference这个是远程调用,如果没有远程调用,直接autowired就可以@dubboreference(version = "${sheet.rvice.version}")private baiducloudbosrvice baiducloudbosrvice;//通过加锁保证线程安全private maphore lock = new maphore(1);//api开头的这些是swagger用到的,如果没使用swagger可以删到postmapping上边@apioperation(value = "obj模型上传")@apiimplicitparams({@apiimplicitparam(name = "totalsize", value = "文件总大小",datatypeclass = long.class),@apiimplicitparam(name = "chunks", value = "总切片数",datatypeclass = integer.class),@apiimplicitparam(name = "chunk", value = "当前切片数",datatypeclass = integer.class),@apiimplicitparam(name = "model", value = "车型",datatypeclass = string.class),@apiimplicitparam(name = "file", value = "切片文件",datatypeclass = multipartfile.class)})@log(title = "obj模型上传", businesstype = businesstype.inrt)@postmapping("/upload3dtobos")public object upload3dtobos( mutilfileinfo fileinfo, @requestparam(required=fal,value="file") multipartfile multipartfile) {string model=fileinfo.getmodel().trim();map<string,object> m=new hashmap();string filename=fileinfo.getname();if (stringutils.impty(filename)) {//判断文件名称是否为空m.put("key","error");m.put("value","文件名不能为空");return m;}if (multipartfile == null) {//判断上传过来的切片是否为空m.put("key","error");m.put("value","请上传文件");return m;}try{string filepath="/test/"+model+"/"+filename;//拼接百度云地址string rediskey="partetags-"+model+"-"+filename;//缓存的键integer current =fileinfo.getchunk();//当前切片数integer total = fileinfo.getchunks();//总切片数long size=multipartfile.getsize();//文件大小string uploadid = getuploadid(rediskey, filepath);//该方法获取百度云的唯一标识uploadidbyte[] file = multipartfile.getbytes();//将切片过来的文件转成字节数组if(current==1){//这块进行断点续传,如果是第一个切片,查询一下缓存中是否有数据了,如果有返回给前台,如果没有进行上传if(getcurrentequalsone(rediskey).size()>0) {//给前台提供是否缓存中已有数据return getcurrentequalsone(rediskey);}}//切片上传百度云list<custompartetag> custompartetags = getpartetags(rediskey, uploadid, filepath, file, size, current);//如果缓存中成功的切片数等于总数,那么进行合并if (custompartetags.size() == total) {custompartetags = custompartetags.stream().sorted(comparator.comparing(partetag::getpartnumber)).collect(collectors.tolist());//进行排序baid职高可以考本科吗ucloudbosrvice.completepart(uploadid, custompartetags, filepath);//执行合并redisutils.hdel(rediskey,"uploadid","custompartetags");//如果合并成功,删除缓存中的数据// 入库做记录m.put("key","success");m.put("value","上传成功");return m;}m.put("key","continue");m.put("value",current+1);return m;}catch (exception e){e.printstacktrace();m.put("key","error");m.put("value","上传失败");return m;}}/*** 获取 part** @param redispartkey rediskey* @return*/private list<custompartetag> 连南党建网getpartetags(string redispartkey, string uploadid, string filepath,  byte[] file, long size, int current) {list<custompartetag> custompartetags = null;try {lock.acquire();//因为每次上传成功后都会把成功的切片存进百度云,如注解下方第四行代码,所以每次上传之前需要先取出来,将成功的切片放进去custompartetags = redisutils.hget(redispartkey, "custompartetags") == null ? new arraylist<>() : json.pararray((string) redisutils.hget(redispartkey, "custompartetags"), custompartetag.class);//上传百度云成功之后会返回一个partetagg对象,由于项目中存在dubbo,顾将custompartetag类继承partetagg进行序列化custompartetag custompartetag = baiducloudbosrvice.uploadcustompartetag(uploadid, filepath, file, size, current);custompartetags.add(custompartetag);tpartetagstoredis(redispartkey, custompartetags);} catch (interruptedexception e) {e.printstacktrace();} finally {lock.relea();}return custompartetags;}/*** 获取 uploadid** @param redispartkey rediskey* @param filepath     filepath* @return*/private string getuploadid(string redispartkey, string filepath) {string uploadid = null;try {lock.acquire();//线程锁uploadid = (string) redisutils.hget(redispartkey, "uploadid");//先去redis中找,是否已经有uploadidif (stringutils.impty(uploadid)) {//判断是否为空,如果为空,说明之前没上传过,为首次上传,如果已经存在,返回该uploadiduploadid = baiducloudbosrvice.initmultipartupload(filepath);//进行初始化,返回一个唯一标识uploadidredisutils.ht(redispartkey, "uploadid", uploadid, 60 * 60);//将返回来的uploadid放到缓存中,下个切片上传直接使用这个uploadid}} catch (interruptedexception e) {e.printstacktrace();} finally {lock.relea();}return uploadid;}/*** 薄墩 partkey到redis** @param redispartkey* @param custompartetags*/private void tpartetagstoredis(string redispartkey, list<custompartetag> custompartetags) {redisutils.ht(redispartkey, "custompartetags", json.tojsonstring(custompartetags), 60 * 60);}public map<string,object> getcurrentequalsone(string rediskey){map<string,object> m=new hashmap<>();list<custompartetag>  custompartetags = redisutils.hget(rediskey, "custompartetags") == null ? new arraylist<>() : json.pararray((string) redisutils.hget(rediskey, "custompartetags"), custompartetag.class);//给前台提供是否缓存中已有数据if(custompartetags.size()==0){return m;}el{//缓存中有数据,返回缓存中数据int t=  custompartetags.get(custompartetags.size()-1).getpartnumber();m.put("key","hasvalue");m.put("value",t);return  m;}}}

3.远程的rvice

(如果不用远程调用,直接创建一个rvice就可以)

package com.geely.tcm.sheet.rvice;import com.baidubce.rvices.bos.bosclient;import com.baidubce.rvices.bos.model.*;import com.geely.tcm.common.bean.baidu.bosresult;import com.geely.tcm.common.bean.baidu.custompartetag;import com.geely.tcm.common.util.stringutils;import com.geely.tcom.remote.api.baidu.baiducloudbosrvice;import lombok.extern.slf4j.slf4j;import org.apache.dubbo.config.annotation.dubborvice;import org.springframework.beans.factory.annotation.autowired;import java.io.*;import java.net.url;import java.util.arraylist;import java.util.list;/*** 百度私有云服务操作** @author : wangbin* @date : 2021/9/24* @since : 1.0.0*/@slf4j@dubborvice(version = "${sheet.rvice.version}")public class baiducloudbosrviceimpl{@autowiredprivate bosclient bosclient;public string initmultipartupload(string filepath) {// 开始multipart uploadinitiatemultipartuploadrequest initiatemultipartuploadrequest = new initiatemultipartuploadrequest(null, filepath);initiatemultipartuploadrespon initiatemultipartuploadrespon = bosclient.initiatemultipartupload(initiatemultipartuploadrequest);// 打印uploadid,它是区分分块上传事件的唯一标识string uploadid = initiatemultipartuploadrespon.getuploadid();log.info("filepath= {},uploadid = {}", filepath, uploadid);return uploadid;}public custompartetag uploadcustompartetag(string uploadid, string filepath, byte[] file, long partsize, int partnumber) {uploadpartrequest uploadpartrequest = new uploadpartrequest();uploadpartrequest.tbucketname(null);uploadpartrequest.tkey(filepath);uploadpartrequest.tuploadid(uploadid);inputstream input= new bytearrayinputstream(file);uploadpartrequest.tinputstream(input);uploadpartrequest.tpartsize(partsize);uploadpartrequest.tpartnumber(partnumber );uploadpartrequest.tmd5digest("");uploadpartrespon uploadpartrespon = bosclient.uploadpart(uploadpartrequest);partetag partetag = uploadpartrespon.getpartetag();custompartetag  custompartetag = new custompartetag();custompartetag.tetag(partetag.getetag());custompartetag.tpartnumber(partetag.getpartnumber());return custompartetag;}/*** 分块上传结束之后,当所有的数据part验证通过后,bos将把这些数据part组合成一个完整的object** @param uploadid* @param custompartetags* @param filepath*/public void completepart(string uploadid, list<custompartetag> custompartetags, string filepath) {//for循环转一下 custompar材料员工作总结tetag 转partetagif(custompartetags.size()>0){list<partetag> partetags=new arraylist<>();for(custompartetag c:custompartetags){partetag partetag=new partetag();partetag.tetag(c.getetag());partetag.tpartnumber(c.getpartnumber());partetags.add(partetag);}completemultipartuploadrequest completemultipartuploadrequest = new completemultipartuploadrequest(null, filepath, uploadid, partetags);completemultipartuploadrespon completemultipartuploadrespon = bosclient.completemultipartupload(completemultipartuploadrequest);log.info("完成分片上传 , filepath = {},uploadid = {}, etag = {}", filepath, uploadid,completemultipartuploadrespon.getetag());}}}

4.定义一个实体类

继承,实现序列化,(dubbo不序列化就会传不过去)

import com.baidubce.rvices.bos.model.partetag;import java.io.rializable;public class custompartetag extends partetag implements rializable {}

5.这里提供一个临时测试的前端代码

<html lang="en"><head><meta chart="utf-8"><title>王宝莹;upload</title><script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script></head><body><input type="file" name="file" id="file"><button id="upload" onclick="upload()">upload</button><script type="text/javascript">var bytesperpiece = 1024 * 1024; // 每个文件切片大小定为1mb .var totalpieces;function upload() {var blob = document.getelementbyid("file").files[0];var start = 0;var end;var index = 1;var filesize = blob.size;var filename = blob.name;//计算文件切片总数totalpieces = math.ceil(filesize / bytesperpiece);while(start < filesize) {end = start + bytesperpiece;if(end > filesize) {end = filesize;}var chunk = blob.slice(start,end);//切割文件    var sliceindex= blob.name + index;var formdata = new formdata();formdata.append("file", chunk, filename);formdata.append("totalsize",filesize);formdata.append("chunks",totalpieces);formdata.append("chunk",index);formdata.append("model",'kx11');$.ajax({//路径换成你的路径url: 'http://127.0.0.1:6300/threemodel/upload3dtobos',type: 'post',datatype:'json',cache: fal,data: formdata,processdata: fal,contenttype: fal,mimetype: "multipart/form-data",success: function (result){console.log(result.value);}});start = end;index++;}}</script></body></html>

到此这篇关于java实现文件切片上传百度云+断点续传的方法的文章就介绍到这了,更多相关java 文件切片上传 内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 04:51:01,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/e72d87dae7375970a8b54f5c3f39d81b.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:java实现文件切片上传百度云+断点续传的方法.doc

本文 PDF 下载地址:java实现文件切片上传百度云+断点续传的方法.pdf

标签:切片   上传   文件   缓存
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图