Amazon S3的分段上传,大文件上传,上传进度条,列出分段上传,中止分段上传,重启续传功能实现

我们在上传大文件的时候往往需要采用分片的方式,Amazon虽然提供了这种方式,但是不能实现我们后端在(宕机/重启)之后导致的文件丢失,大文件上传到一半可能会丢失数据的问题。

本文将利用本地线程池加数据库记录的方式,实现后端(宕机/重启)后恢复之前正在上传的文件,顺便利用SSE(Server Send Event)实现(宕机/重启)后进度条的还原。

首先引入maven,我用的是下面这个,目前最新版本1.12.731。

<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-java-sdk-s3</artifactId>
    <version>1.12.731</version>
</dependency>
​
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.16.1</version>
</dependency>

配置AmazonS3客户端

新建WebConfig,这里用BasicAWSCredentials创建基础的AWS认证,并在Spring中注入AmazonS3 的bean方便后续使用

// WebConfig.java
​
@Configuration
public class WebConfig {
​
    private static final String accessKey = "你的accessKey";
​
    private static final String secretKey = "你的secretKey";
​
    @Bean
    public AmazonS3 s3() {
        BasicAWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
        return AmazonS3Client.builder()
                .withRegion(Regions.CN_NORTHWEST_1)// 可以根据自己的需求进行选择
                .withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
                .build();
    }
    
    @Bean
    public ExecutorService executorService() {
        return Executors.newFixedThreadPool(10);
    }
​
    @Bean
    public ConcurrentMap<String, MyThread> uploadingFileMap() {
        return new ConcurrentHashMap<>();
    }
}

文件上传

让我们首先实现一个基础版本的分段文件上传

新建一个文件S3UploadController

// S3UploadController.java
private static final String bucketName = "testbuckname";
​
private final AmazonS3 s3;
​
private File curFile = null;
​
long filePosition = 0;
​
@PostMapping("/file")
public String file(MultipartFile file) throws IOException {
    //重复上传直接忽略掉
    if (curFile != null) {
        return "等待其他文件上传完毕";
    }
    // 基于客户端认证创建TransferManager,它的主要功能是上传文件请求,等待上传完毕。
    TransferManager tm = TransferManagerBuilder.standard().withS3Client(s3).build();
   
    InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, monthAndDayDir() + file.getOriginalFilename());
    InitiateMultipartUploadResult initResponse = s3.initiateMultipartUpload(initRequest);
    if (file.getOriginalFilename() == null) {
        return "file is null";
    }
    // 文件上传位置(B)
    filePosition = 0;
    // 分片大小5MB
    long partSize = 5 * 1024 * 1024;
    int idx = file.getOriginalFilename().lastIndexOf(".");
    // 创建临时文件,为什么要创建临时文件不用传入的file?,下面方法中只能用File类型,需要将MultipartFile转为File类型
    curFile = File.createTempFile(file.getOriginalFilename().substring(0, idx), file.getOriginalFilename().substring(idx));
    // 流传输,需要commons-io,要引入pom
    FileUtils.copyInputStreamToFile(file.getInputStream(), curFile);
    long contentLength = file.getSize();
    // 监听
    List<PartETag> partETags = new ArrayList<>();
​
    // 这里需要开一个线程使用SSE 监听,下面会描述
    MyThread myThread = new MyThread(tm, bucketName, curFile, 0, uploadingFileMap, initResponse.getUploadId(), links, service, partETags);
    // 线程存到本地线程里面
    uploadingFileMap.put(initResponse.getUploadId(), myThread);
    // 运行
    executorService.submit(myThread);
​
    // 分段上传开始
    for (int i = 1; filePosition < contentLength; i++) {
​
        partSize = Math.min(partSize, (contentLength - filePosition));
        UploadPartRequest uploadRequest = new UploadPartRequest()
 &
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你熬夜了吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值