• 文件上传,还存储在应用服务器?


    前言

    一般项目开发中都会有文件、图片、视频等文件上传并能够访问的场景。要实现这样的场景,要么把文件存储在应用服务器上,要么搭建文件服务来存储。但是这两种方式也有不少的缺点,增加运维的成本。

    因此,追求用户体验的项目可能会考虑使用第三方的云服务来实现存储,目前市场上主流的厂商有:七牛云、阿里云OSS、腾讯云COS等,具体采用哪种存储方案还需结合项目的规模、成本等因素,综合考量。

    因为我的是腾讯云的服务器,所以就直接开通了腾讯云的COS对象存储。这篇文章就来记录一下,SpringBoot整合腾讯云COS对象存储实现文件上传的。


    一、准备工作

    整合前需要做一些准备工作,开通COS对象存储,创建存储通,创建访问密钥。

    1. 开通腾讯云对象存储服务

    新用户专享,1米可以购买1年的存储。用来学习还是很香的。console.cloud.tencent.com/cos

    2. 创建存储桶

    注意存储桶访问的访问权限,设置成公有读私有写。

    3. 密钥管理,创建密钥

    点击新建密钥,会自动生成。

    三、整合步骤

    1. 添加maven依赖

    代码如下(示例):

    1. <!--腾讯云 COS 对象存储-->
    2. <dependency>
    3. <groupId>com.qcloud</groupId>
    4. <artifactId>cos_api</artifactId>
    5. <version>5.6.89</version>
    6. </dependency>
    7. 复制代码

    2. yml文件增加配置

    代码如下(示例):

    1. # 腾讯云cos配置
    2. cos:
    3. baseUrl: https://xiliu-******24.cos.ap-guangzhou.myqcloud.com
    4. secretId: AKI******************ior
    5. secretKey: zZ*************z6
    6. regionName: ap-guangzhou
    7. bucketName: xiliu-******24
    8. folderPrefix: /upload
    9. 复制代码

    3. 新建 COS 配置类

    代码如下(示例):

    1. package com.java.xiliu.config;
    2. import lombok.Data;
    3. import org.springframework.boot.context.properties.ConfigurationProperties;
    4. import org.springframework.stereotype.Component;
    5. /**
    6. * @author xiliu
    7. * @description 腾讯云cos对象存储配置类
    8. * @date 2022/10/28
    9. */
    10. @Data
    11. @Component
    12. @ConfigurationProperties(prefix = "cos")
    13. public class CosConfig {
    14. /**
    15. * 存储桶访问路径
    16. **/
    17. private String baseUrl;
    18. /**
    19. * 腾讯云账号秘钥
    20. **/
    21. private String secretId;
    22. /**
    23. * 密码秘钥
    24. **/
    25. private String secretKey;
    26. /**
    27. * 存储桶地区
    28. **/
    29. private String regionName;
    30. /**
    31. * 存储桶名称
    32. **/
    33. private String bucketName;
    34. /**
    35. * 上传的根目录
    36. **/
    37. private String folderPrefix;
    38. public COSClient getCosClient() {
    39. // 初始化用户信息
    40. COSCredentials cosCredentials = new BasicCOSCredentials(this.secretId,this.secretKey);
    41. // 设置地域
    42. Region region = new Region(this.regionName);
    43. ClientConfig config = new ClientConfig(region);
    44. // 生成COS客户端
    45. COSClient client = new COSClient(cosCredentials,config);
    46. return client;
    47. }
    48. }
    49. 复制代码

    4. 新建 COS 上传工具类

    代码如下(示例):

    1. package com.java.xiliu.common.untils.file;
    2. import com.java.xiliu.common.untils.SpringUtils;
    3. import com.java.xiliu.config.CosConfig;
    4. import com.qcloud.cos.COSClient;
    5. import com.qcloud.cos.model.PutObjectRequest;
    6. import com.qcloud.cos.model.UploadResult;
    7. import com.qcloud.cos.transfer.TransferManager;
    8. import com.qcloud.cos.transfer.Upload;
    9. import lombok.extern.slf4j.Slf4j;
    10. import org.apache.commons.io.FilenameUtils;
    11. import org.springframework.web.multipart.MultipartFile;
    12. import java.io.File;
    13. import java.io.IOException;
    14. import java.util.concurrent.ArrayBlockingQueue;
    15. import java.util.concurrent.ThreadPoolExecutor;
    16. import java.util.concurrent.TimeUnit;
    17. /**
    18. * @author xiliu
    19. * @description 腾讯云COS文件上传工具类
    20. * @date 2022/10/31
    21. */
    22. @Slf4j
    23. public class CosClientUtils {
    24. /**
    25. * 获取配置信息
    26. */
    27. private static CosConfig cosConfig = SpringUtils.getBean(CosConfig.class);
    28. public static String upload(MultipartFile file, String dir) throws Exception {
    29. String originalFilename = file.getOriginalFilename();
    30. // 文件名
    31. String name = FilenameUtils.getBaseName(originalFilename) + "_" + System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf("."));
    32. // 目录
    33. String folderName = cosConfig.getFolderPrefix() + "/" + dir + "/";
    34. String key = folderName + name;
    35. File localFile = null;
    36. try {
    37. localFile = transferToFile(file);
    38. String filePath = uploadFileToCos(localFile, key);
    39. log.info("upload COS successful: {}", filePath);
    40. return filePath;
    41. } catch (Exception e) {
    42. throw new Exception("文件上传失败");
    43. } finally {
    44. localFile.delete();
    45. }
    46. }
    47. /**
    48. * 用缓冲区来创建临时文件
    49. * 使用 MultipartFile.transferTo()
    50. * @param multipartFile
    51. * @return
    52. */
    53. private static File transferToFile(MultipartFile multipartFile) throws IOException {
    54. String originalFilename = multipartFile.getOriginalFilename();
    55. String prefix = originalFilename.split("\\.")[0];
    56. String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
    57. File file = File.createTempFile(prefix, suffix);
    58. multipartFile.transferTo(file);
    59. return file;
    60. }
    61. /**
    62. * 上传文件到COS
    63. * @param localFile
    64. * @param key
    65. * @return
    66. */
    67. private static String uploadFileToCos(File localFile, String key) throws InterruptedException {
    68. PutObjectRequest putObjectRequest = new PutObjectRequest(cosConfig.getBucketName(), key, localFile);
    69. // 获取连接
    70. COSClient cosClient = cosConfig.getCosClient();
    71. // 创建线程池
    72. ThreadPoolExecutor threadPool = new ThreadPoolExecutor(8, 16,
    73. 4, TimeUnit.SECONDS, new ArrayBlockingQueue(10), new ThreadPoolExecutor.AbortPolicy());
    74. // 传入一个threadPool, 若不传入线程池, 默认TransferManager中会生成一个单线程的线程池
    75. TransferManager transferManager = new TransferManager(cosClient, threadPool);
    76. // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常
    77. Upload upload = transferManager.upload(putObjectRequest);
    78. UploadResult uploadResult = upload.waitForUploadResult();
    79. transferManager.shutdownNow();
    80. cosClient.shutdown();
    81. String filePath = cosConfig.getBaseUrl() + uploadResult.getKey();
    82. return filePath;
    83. }
    84. }
    85. 复制代码

    5. 新建 Controller 上传接口

    代码如下(示例):

    1. @ApiOperation(value = "用户头像上传")
    2. @PostMapping("/profile/avatar")
    3. public R uploadAvatar(@RequestParam("avatarfile") MultipartFile file) throws Exception {
    4. if (!file.isEmpty()) {
    5. String avatar = CosClientUtils.upload(file, "avatar");
    6. return R.ok(avatar);
    7. }
    8. return R.error("上传头像异常,请联系管理员");
    9. }
    10. 复制代码

    6. 测试

    使用 Swagger 接口文档或者Postman测试上传接口,成功返回地址。使用浏览器打开该返回地址,可以正常预览。


    总结

    以上就是本文的全部内容了,感谢大家的阅读。

    如果觉得文章对你有帮助,还不忘帮忙点赞、收藏、关注、评论哟,您的支持就是我创作最大的动力!

  • 相关阅读:
    tsx 文件中的 行删除
    程序化交易(二)level2行情数据源接入
    django setting.py中的SECRET_KEY
    RabbitMQ_概述
    点餐小程序实战教程02用户注册
    2000-2022年“宽带Z国“试点城市名单匹配数据
    windows上安装好了pip,并正确配置了路径后,特别地使用
    原来你不会找资源,三个宝藏白嫖书籍网站,阅读改变生活(一)
    多尺度分别融合方法
    GO微服务实战第一节 为什么说云原生重构了互联网产品开发模式?
  • 原文地址:https://blog.csdn.net/m0_71777195/article/details/127785981