Alibaba Cloud 实现大文件上传

在 Spring Boot 项目中使用阿里云平台实现大文件存储,并提升文件的存储与读取效率,可以通过集成阿里云的对象存储服务(OSS)。阿里云 OSS 是一个海量、安全、低成本、高可靠的云存储服务,非常适合大文件存储需求。

配置阿里云 OSS 客户端

创建配置类来初始化 OSS 客户端。需要获取阿里云的 AccessKeyId、AccessKeySecret 以及 Endpoint。

@Configuration
public class OssConfig {

    private String endpoint = "https://oss-cn-your-region.aliyuncs.com"; // 替换为实际的endpoint
    private String accessKeyId = "your-access-key-id";  // 替换为实际的AccessKeyId
    private String accessKeySecret = "your-access-key-secret";  // 替换为实际的AccessKeySecret

    @Bean
    public OSS ossClient() {
        return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
}

上传文件到 OSS

通过 Spring Boot 的 @Service 注解创建一个服务类,来实现上传大文件到 OSS。

@Service
public class OssService {

    @Autowired
    private OSS ossClient;

    private String bucketName = "your-bucket-name";  // 替换为你的Bucket名称

    public String uploadFile(MultipartFile file) throws Exception {
        String fileName = file.getOriginalFilename();
        InputStream inputStream = file.getInputStream();

        // 将文件上传到指定的存储桶
        ossClient.putObject(bucketName, fileName, inputStream);

        // 返回文件的访问URL
        return "https://" + bucketName + ".oss-cn-your-region.aliyuncs.com/" + fileName;
    }
}

文件下载

提供文件下载接口,以便能够从 OSS 上读取文件。

@Service
public class OssDownloadService {

    @Autowired
    private OSS ossClient;

    private String bucketName = "your-bucket-name";

    public InputStream downloadFile(String fileName) {
        // 从OSS下载文件
        return ossClient.getObject(bucketName, fileName).getObjectContent();
    }
}

提升存储与读取效率的建议

  • 分片上传:对于大文件,阿里云 OSS 支持分片上传,这样可以大大提升上传效率。分片上传的工作原理是将大文件分割成多个小片段分别上传,最后再合并。
  • CDN 加速:如果文件主要用于静态资源访问,可以启用阿里云的 CDN(内容分发网络)来加速文件读取和下载,特别是提升地理分布式的用户访问速度。
  • 并发处理:对于文件上传和下载,可以通过异步或多线程的方式提高效率。

分片上传示例

使用阿里云 OSS 提供的 MultipartUploadRequest 来实现分片上传。

@Service
public class OssMultipartUploadService {

    @Autowired
    private OSS ossClient;

    private String bucketName = "your-bucket-name";

    public String multipartUpload(MultipartFile file) throws Exception {
        String fileName = file.getOriginalFilename();
        InputStream inputStream = file.getInputStream();

        // 初始化分片上传
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, fileName);
        String uploadId = ossClient.initiateMultipartUpload(request).getUploadId();

        List<PartETag> partETags = new ArrayList<>();
        int partSize = 1024 * 1024 * 5;  // 每个分片5MB
        byte[] buffer = new byte[partSize];
        int bytesRead;
        int partNumber = 1;

        while ((bytesRead = inputStream.read(buffer)) != -1) {
            UploadPartRequest uploadPartRequest = new UploadPartRequest();
            uploadPartRequest.setBucketName(bucketName);
            uploadPartRequest.setKey(fileName);
            uploadPartRequest.setUploadId(uploadId);
            uploadPartRequest.setInputStream(inputStream);
            uploadPartRequest.setPartSize(bytesRead);
            uploadPartRequest.setPartNumber(partNumber++);

            partETags.add(ossClient.uploadPart(uploadPartRequest).getPartETag());
        }

        // 完成分片上传
        CompleteMultipartUploadRequest completeMultipartUploadRequest = 
                new CompleteMultipartUploadRequest(bucketName, fileName, uploadId, partETags);
        ossClient.completeMultipartUpload(completeMultipartUploadRequest);

        return "https://" + bucketName + ".oss-cn-your-region.aliyuncs.com/" + fileName;
    }
}

断点续传示例

  • 在 Spring Boot 项目中,使用阿里云 OSS(对象存储服务)上传大文件时,可以引入断点续传机制来确保大文件上传过程中因网络波动或其他原因中断时,能够从中断的地方继续上传。阿里云 OSS SDK 提供了断点续传上传的功能,称为 Resumable Upload。该内置的断点续传上传功能,可以通过 OSSResumableUpload 来实现。该功能会自动记录上传的状态,并在下次上传时恢复进度。
  • 断点续传是基于分片上传实现的,因此它包括了多线程、也包括了上传失败后重试机制。

断点续传功能需要在上传过程中自动保存上传进度,可以通过阿里云的 OSSResumableUpload API 实现。

@Service
public class OssResumableUploadService {

    @Autowired
    private OSS ossClient;

    private String bucketName = "your-bucket-name"; // 替换为你的bucket名称

    public String resumableUpload(MultipartFile multipartFile) throws Exception {
        String fileName = multipartFile.getOriginalFilename();
        String localTempFilePath = "/tmp/" + fileName; // 需要有临时存储路径来保存中间文件

        // 将 MultipartFile 保存到本地的临时文件
        File tempFile = new File(localTempFilePath);
        multipartFile.transferTo(tempFile);

        // 配置分片大小,并且设置本地记录文件来记录进度
        UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, fileName);
        uploadFileRequest.setUploadFile(tempFile.getPath());
        uploadFileRequest.setPartSize(1024 * 1024 * 5); // 设置每个分片的大小为5MB
        uploadFileRequest.setTaskNum(5); // 设置并发线程数
        uploadFileRequest.setEnableCheckpoint(true); // 启用断点续传

        // 执行断点续传上传
        ossClient.uploadFile(uploadFileRequest);

        // 清理临时文件
        tempFile.delete();

        // 返回文件的访问URL
        return "https://" + bucketName + ".oss-cn-your-region.aliyuncs.com/" + fileName;
    }
}
  • 临时文件存储:将 MultipartFile 转换为本地文件,因为阿里云 OSS 的断点续传需要依赖本地文件来记录上传的进度。
  • 分片大小和并发控制:设置了每个分片的大小为 5MB,并使用 5 个并发线程来上传,提升上传效率。
  • 断点续传启用:通过 setEnableCheckpoint(true) 启用断点续传机制。阿里云 OSS 会在本地生成一个 .ossupload 的文件,记录上传的进度。如果上传中断,重新调用该方法时会自动从上次中断的地方继续上传。
  • 删除临时文件:上传成功后,将本地的临时文件删除。

可以实现上传进度回调,以便在上传过程中获取当前的上传状态:

uploadFileRequest.setProgressListener(new ProgressListener() {
    @Override
    public void progressChanged(ProgressEvent progressEvent) {
        long bytes = progressEvent.getBytes();
        System.out.println("Uploaded bytes: " + bytes);
    }
});
  • 断点续传不仅限于上传,在文件下载过程中,也可以通过阿里云 OSS 提供的 ResumableDownloadRequest 实现断点续传下载。如果下载过程中断,可以从中断处继续。
  • 在阿里云 OSS 的文件断点续传下载中,默认情况下没有内置的自动重试功能。但是,阿里云 OSS SDK 支持对下载失败后的手动重试,也就是说,如果下载失败,可以自行实现重试逻辑,结合断点续传的功能,从中断处继续下载。
@Service
public class OssDownloadServiceWithRetry {

    @Autowired
    private OssClientService ossClientService;

    public void downloadFileWithRetry(String objectName, String downloadFilePath, int maxRetryCount) throws Throwable {
        OSS ossClient = ossClientService.createOssClient();
        int retryCount = 0;
        boolean downloadSuccess = false;

        while (!downloadSuccess && retryCount < maxRetryCount) {
            try {
                // 设置断点续传下载请求
                DownloadFileRequest downloadFileRequest = new DownloadFileRequest(ossClientService.getBucketName(), objectName);
                downloadFileRequest.setDownloadFile(downloadFilePath);  // 本地存储路径
                downloadFileRequest.setPartSize(1024 * 1024 * 5);  // 设置每个分片的大小为5MB
                downloadFileRequest.setTaskNum(5);  // 设置并发下载线程数
                downloadFileRequest.setEnableCheckpoint(true);  // 启用断点续传

                // 下载文件
                DownloadFileResult downloadFileResult = ossClient.downloadFile(downloadFileRequest);
                downloadSuccess = true;  // 下载成功
                System.out.println("文件下载成功,ETag:" + downloadFileResult.getObjectMetadata().getETag());
            } catch (Throwable t) {
                retryCount++;
                System.err.println("文件下载失败,重试次数:" + retryCount);
                if (retryCount >= maxRetryCount) {
                    throw new Exception("文件下载失败,超过最大重试次数");
                }
            }
        }

        // 关闭OSS客户端
        ossClient.shutdown();
    }
}
  • 断点续传功能:阿里云 OSS SDK 提供的断点续传会自动记录下载进度,生成本地 .ossdownload 文件,当下载中断或失败后,SDK 可以从中断的地方继续下载。
  • 重试机制:可以通过自定义重试逻辑,实现对下载失败的重试操作。每次重试会基于上次中断处继续,不需要从头开始下载。
  • 最大重试次数:为了避免无限重试,可以设置一个合理的最大重试次数,例如网络条件不好时,允许重试 3-5 次。

在 Spring Boot 项目中,通过阿里云 OSS 结合 CDN 可以实现大文件的加速访问。阿里云 OSS 提供了存储服务,而 CDN(内容分发网络)通过将资源分发到全球的边缘节点,减少延迟并提高访问速度。结合这两者,用户可以快速、高效地访问存储在 OSS 上的大文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值