阿里云OSS-大文件-分片上传
首先抱歉我忘记了最初版本是摘自哪位大牛的了,实在不好意思,感谢他/她;
粗糙测试:postman同时(相差2秒内)send请求访问阿里云OSS的普通上传和分片上传212MB的eclipse-jee-indigo-SR2-64.zip;
得到21:7:13========21:9:7(分片)--->耗时2分钟
得到21:7:11================21:15:23(普通上传)--->耗时8分钟
至于拿配置文件里面的值的方法.恕我不能展示出来,那些是公司的代码, 其实也很简单,但是使用的是公司内部封装的,其实底层也就是jdk的api, 并且这种方式是比较老的,不是框架直接注解@就导入. 大家用自己习惯的方式注入值就好了.(建议不要把值直接写在类里)
整个类import比较简单 只有aliyunOss必须的一个sdk:《aliyun-sdk-oss-2.3.0.jar》
注意:
①由于是测试, 所以这个工具类我给它加了@Controller注解和对应的接口url,实际运用时, emmmm,你们自己看着办吧。当工具类调用也可以,直接当上传视频的接口也可以。
②由于是测试, 我返回return的是时间差, 你们要用来上传到阿里云OSS储存桶的时候把 被注释掉的那行return解封,把下面的时间代码删除即可。
````
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import com.aliyun.oss.OSSClient;
/*** @author Berton* @time: 2018年2月11日 下午14:23:12*/
@Controller
public class FileUploader {private static String endpoint = "";//买的阿里云的位置private static String accessKeyId = "";//阿里云账号的KeyIdprivate static String accessKeySecret = "";//阿里云账号的KeySecretprivate static String bucketName = "";//阿里云上自己桶的名字protected static OSSClient client = null;//创建阿里云服务器连接对象private static Logger logger = LoggerFactory.getLogger(FileUploader.class);@RequestMapping(value = "heiheihei", method = { RequestMethod.POST })@ResponseBodypublic static String fileUpload(MultipartFile file) {Date date = new Date();String beginTime = date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();OSSConfig config = null;// 创建一个可重用固定线程数的线程池。若同一时间线程数大于10,则多余线程会放入队列中依次执行ExecutorService executorService = Executors.newFixedThreadPool(10);// 完整的文件名String key = file.getOriginalFilename();// 创建OSSClient实例config = config == null ? new OSSConfig() : config;//从自己的配置文件里面取值endpoint = config.getEndpoint();accessKeyId = config.getAccessKeyId();accessKeySecret = config.getAccessKeySecret();bucketName = config.getBucketName();client = new OSSClient(endpoint, accessKeyId, accessKeySecret);//根据阿里云用户配置创建连接对象实例try {String uploadId = AliyunOSSUpload.claimUploadId(bucketName, key);// key是文件名 By berton// 设置每块为 5M(除最后一个分块以外,其他的分块大小都要大于5MB)final long partSize = 5 * 1024 * 1024L;// 计算分块数目long fileLength = file.getSize();// 文件大小int partCount = (int) (fileLength / partSize);// 文件大小%分块大小if (fileLength % partSize != 0) {partCount++;}// 分块 号码的范围是1~10000。如果超出这个范围,OSS将返回InvalidArgument的错误码。if (partCount > 10000) {throw new RuntimeException("文件过大(分块大小不能超过10000)");} else {logger.info("一共分了 " + partCount + " 块");}/*** 将分好的文件块加入到list集合中*/for (int i = 0; i < partCount; i++) {// 起始pointlong startPos = i * partSize;// 判断当前partSize的长度 是否最后一块long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;// 线程执行。将分好的文件块加入到list集合中()executorService.execute(new AliyunOSSUpload(file, startPos, curPartSize, i + 1, uploadId, key, bucketName));}/*** 等待所有分片完毕*/// 关闭线程池(线程池不马上关闭),执行以前提交的任务,但不接受新任务。executorService.shutdown();// 如果关闭后所有任务都已完成,则返回 true。while (!executorService.isTerminated()) {try {// 用于等待子线程结束,再继续执行下面的代码executorService.awaitTermination(5, TimeUnit.SECONDS);} catch (InterruptedException e) {e.printStackTrace();}}/*** partETags(上传块的ETag与块编号(PartNumber)的组合) 如果校验与之前计算的分块大小不同,则抛出异常*/System.out.println(AliyunOSSUpload.partETags.size() + " ----- " + partCount);if (AliyunOSSUpload.partETags.size() != partCount) {throw new IllegalStateException("OSS分块大小与文件所计算的分块大小不一致");} else {logger.info("将要上传的文件名 " + key + "\n");}/** 列出文件所有的分块清单并打印到日志中,该方法仅仅作为输出使用*/AliyunOSSUpload.listAllParts(uploadId);/** 完成分块上传*/AliyunOSSUpload.completeMultipartUpload(uploadId);// 返回上传文件的URL地址// return endpoint.replaceFirst("http://","http://"+bucketName+".")+"/"+key ;Date date2 = new Date();String endTime = date2.getHours() + ":" + date2.getMinutes() + ":" + date2.getSeconds();return beginTime + "========" + endTime;} catch (Exception e) {logger.error("上传失败!", e);return "上传失败!";} finally {AliyunOSSUpload.partETags.clear();if (client != null) {client.shutdown();}}}
}
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile; import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.CompleteMultipartUploadRequest;
import com.aliyun.oss.model.InitiateMultipartUploadRequest;
import com.aliyun.oss.model.InitiateMultipartUploadResult;
import com.aliyun.oss.model.ListPartsRequest;
import com.aliyun.oss.model.PartETag;
import com.aliyun.oss.model.PartListing;
import com.aliyun.oss.model.PartSummary;
import com.aliyun.oss.model.UploadPartRequest;
import com.aliyun.oss.model.UploadPartResult; public class AliyunOSSUpload implements Runnable { private MultipartFile localFile; private long startPos; private long partSize; private int partNumber; private String uploadId; private static String key; private static String bucketName; // 新建一个List保存每个分块上传后的ETag和PartNumber protected static List<PartETag> partETags = Collections.synchronizedList(new ArrayList<PartETag>()); private static Logger logger = LoggerFactory.getLogger(FileUploader.class); protected static OSSClient client = null; /** * 创建构造方法 * * @param localFile * 要上传的文件 * @param startPos * 每个文件块的开始 * @param partSize * @param partNumber * @param uploadId * 作为块的标识 * @param key * 上传到OSS后的文件名 */ public AliyunOSSUpload(MultipartFile localFile, long startPos, long partSize, int partNumber, String uploadId, String key , String bucketName) { this.localFile = localFile; this.startPos = startPos; this.partSize = partSize; this.partNumber = partNumber; this.uploadId = uploadId; AliyunOSSUpload.key = key; AliyunOSSUpload.bucketName = bucketName; } /** * 分块上传核心方法(将文件分成按照每个5M分成N个块,并加入到一个list集合中) */ @Override public void run() { InputStream instream = null; try { // 获取文件流 instream = localFile.getInputStream(); // 跳到每个分块的开头 instream.skip(this.startPos); // 创建UploadPartRequest,上传分块 UploadPartRequest uploadPartRequest = new UploadPartRequest(); uploadPartRequest.setBucketName(bucketName); uploadPartRequest.setKey(key); uploadPartRequest.setUploadId(this.uploadId); uploadPartRequest.setInputStream(instream); uploadPartRequest.setPartSize(this.partSize); uploadPartRequest.setPartNumber(this.partNumber); UploadPartResult uploadPartResult = FileUploader.client.uploadPart(uploadPartRequest); logger.info("Part#" + this.partNumber + " done\n"); synchronized (partETags) { // 将返回的PartETag保存到List中。 partETags.add(uploadPartResult.getPartETag()); } } catch (Exception e) { e.printStackTrace(); } finally { if (instream != null) { try { // 关闭文件流 instream.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 初始化分块上传事件并生成uploadID,用来作为区分分块上传事件的唯一标识 * * @return */ protected static String claimUploadId(String bucketName, String key) { InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, key); InitiateMultipartUploadResult result = FileUploader.client.initiateMultipartUpload(request); logger.info(result.getUploadId()); return result.getUploadId(); } /** * 将文件分块进行升序排序并执行文件上传。 * * @param uploadId */ protected static void completeMultipartUpload(String uploadId) { // 将文件分块按照升序排序 Collections.sort(partETags, new Comparator<PartETag>() { @Override public int compare(PartETag p1, PartETag p2) { return p1.getPartNumber() - p2.getPartNumber(); } }); CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, key, uploadId, partETags); // 完成分块上传 FileUploader.client.completeMultipartUpload(completeMultipartUploadRequest); } /** * 列出文件所有分块的清单 * * @param uploadId */ protected static void listAllParts(String uploadId) { ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, key, uploadId); // 获取上传的所有分块信息 PartListing partListing = FileUploader.client.listParts(listPartsRequest); // 获取分块的大小 int partCount = partListing.getParts().size(); // 遍历所有分块 for (int i = 0; i < partCount; i++) { PartSummary partSummary = partListing.getParts().get(i); logger.info("分块编号 " + partSummary.getPartNumber() + ", ETag=" + partSummary.getETag()); } }
} ````
阿里云OSS-大文件-分片上传相关推荐
- 使用阿里云OSS完成文件的上传样例
使用阿里云OSS完成文件的上传 基础条件: 提前注册过阿里云账户 账户里有余额(文件上传按流量收费) 开通过OSS的基础服务 如果有以上基础条件不满足的小伙伴,去度娘了解一下. 前言 有过基础的小伙伴 ...
- 使用阿里云OSS实现文件的上传、下载、删除及修改功能
一.配置OSS相关配置信息 1.要配置 OSS 相关配置信息,您可以按照以下步骤操作: 登录阿里云控制台,进入 OSS 控制台,创建一个新的 OSS Bucket,并记录下以下信息:Bucket 名称 ...
- vue用阿里云oss上传图片使用分片上传只能上传100kb以内的解决办法
首先,vue和阿里云oss上传图片结合参考了 这位朋友的 https://www.jianshu.com/p/645f63745abd 文章,成功的解决了我用阿里云oss上传图片前的一头雾水. 该大神 ...
- AWS-S3通用存储操作,操作minio、oss、cos等所有兼容s3协议的云存储(含有大文件分片上传实现)
一.介绍 通用存储操作common包,支持所有兼容amazon-s3协议的云存储,如minio.oss.cos等,以后客户用啥云储存一套代码都能搞定了,真棒~ 二.代码结构 三.代码实现 3.1 po ...
- 大文件分片上传,断点续传,秒传 实现
前段时间做视频上传业务,通过网页上传视频到服务器. 视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长, ...
- jquery 分片上传php,php 大文件分片上传
前端部分 上传 //上传控件 uploadBig('upload','zip,rar,7z,tar',{ id: '', type: 'upload_file', } ,(res)=>{ //t ...
- 大文件分片上传前端框架_基于Node.js的大文件分片上传
基于Node.js的大文件分片上传 我们在做文件上传的时候,如果文件过大,可能会导致请求超时的情况.所以,在遇到需要对大文件进行上传的时候,就需要对文件进行分片上传的操作.同时如果文件过大,在网络不佳 ...
- Vue项目中遇到了大文件分片上传的问题
Vue项目中遇到了大文件分片上传的问题,之前用过webuploader,索性就把Vue2.0与webuploader结合起来使用,封装了一个vue的上传组件,使用起来也比较舒爽. 上传就上传吧,为什么 ...
- 大文件分片上传前端框架_无插件实现大文件分片上传,断点续传
文件上传.gif 1. 简介: 本篇文章基于实际项目的开发,将介绍项目中关于大文件分片上传.文件验证.断点续传.手动重试上传等需求的使用场景及实现: 2. 项目需求 在一个音视频的添加中,既要有音视频 ...
- 无插件实现大文件分片上传,断点续传
代码地址如下: http://www.demodashi.com/demo/11888.html 1. 简介: 本篇文章基于实际项目的开发,将介绍项目中关于大文件分片上传.文件验证.断点续传.手动重试 ...
最新文章
- Dockerfile 最佳实践
- Oracle与Mysql主键、索引及分页的区别小结
- 在WIN7系统的笔记本上建立WIFI热点
- 【Linux】一步一步学Linux——fg命令(130)
- 关于错误	1	error C4996: 'getch': The POSIX name for this item is deprecated.问题解决方式
- wordpress后台添加子菜单 add_submenu_page()
- windows10和ubuntu双系统win10时间不正确
- python怎么用第三方库_python中第三方库的下载方法
- access month函数用法_小白进阶必备的10组函数公式实用技巧解读,有案例和详情解读哦!...
- jbpm 5 安装教程
- 二进制码转十进制java,Java将二进制转换为十进制
- python局部变量函数_python函数局部变量用法实例分析
- SQL Server中的“描述表”等效什么?
- 基于Android的人事管理系统开发与设计源码(二)
- undefined reference问题总结
- java疯狂讲义第1天
- Ubuntu22.04 x64 下运行同花顺Linux版,解决libssl版本错误问题
- js分割字符串转数组
- vuecli添加和移除插件_『Clickteam Fusion插件开发基础』
- 程序员的自我修养(雾)
热门文章
- SublimeText3中使用terminal终端
- Dubbo详解(一)分布式服务框架的概念理解
- layui让当前页面刷新_layui怎么刷新当前页面
- 胡歌、杨幂or赵丽颖?用Python让你的爱豆陪你度过2019
- 【经典面试题】strcat 函数的实现
- pyspider爬取王者荣耀数据(上)
- 有效延缓痴呆症:延世大学发现梯度提升机模型能准确预测 BPSD 亚综合征
- 苹果支付流程以及服务端php验证
- c#拼图碎片形状_拼图的碎片形状的种类
- 无法读取本地或者服务器版本信息,Windows2003服务器的本地安全策略显示“windows无法读取模板信息”的终极处理解决方案。...