文件上传下载.md 5.0 KB

上传说明

  • 文件上传通过亚马逊s3协议,对多种文件存储服务(包含:minIO,阿里云oss,腾讯云cos,七牛云kodo)进行统一管理,进行文件上传操作
  • 文件上传的流程:后端生成一个带签名并且有时限的url返回给前端,前端通过该签名url进行文件文件上传

后台实现代码

我们查看后台FileController 这里对文件上传的接口进行了统一的管理:

@RestController
@RequestMapping("/admin/file")
@AllArgsConstructor
public class FileController {
    
   private final AttachFileService attachFileService;

    @GetMapping("/getPreSignUrl")
    @Parameters({
            @Parameter(name = "fileName", description = "文件名"),
            @Parameter(name = "isImFile", description = "是否为客服聊天文件")
    })
    @Operation(summary = "获取预签名url(s3协议)")
    public ServerResponseEntity<PreSignUrlVO> getPreSignUrl(String fileName, Boolean isImFile) {
        Long shopId = Constant.PLATFORM_SHOP_ID;
        PreSignUrlVO preSingUrlVO = attachFileService.getPreSingUrl(shopId, fileName, isImFile);
        return ServerResponseEntity.success(preSingUrlVO);
    }
}

同时我们查看AwsS3Config类,里面具体展示如何通过s3协议进行生成签名url,上传文件,删除文件

@Configuration
@RequiredArgsConstructor
public class AwsS3Config {

    private final ShopConfig shopConfig;

    private S3Presigner getS3Presigner(UploadFile config) {
        // aws-s3会自动转成桶域名进行访问(https://bucketName.endpoint),minio不存在桶域名概念,需固定访问路径样式
        boolean isForcePathStyle = Objects.equals(StorageTypeEnum.MINIO.getValue(), config.getStorageType());
        return S3Presigner.builder()
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(config.getAccessKey(), config.getSecretKey())))
                .region(Region.AWS_GLOBAL)
                .endpointOverride(URI.create(config.getEndPoint()))
                .serviceConfiguration(S3Configuration.builder()
                        .pathStyleAccessEnabled(isForcePathStyle)
                        .chunkedEncodingEnabled(false)
                        .build())
                .build();
    }

    /**
     * 获取预签名url
     * @param fileName 文件名(支持路径形式'xx/xx/xxx.png')
     * @return 预签名url
     */
    public String getPreSignUrl(String fileName) {
        UploadFile config = shopConfig.getUploadFile();
        S3Presigner s3Presigner = this.getS3Presigner(config);
        PutObjectPresignRequest presignRequest = this.buildPreSignReq(fileName, config.getBucketName());
        PresignedPutObjectRequest presignedRequest = s3Presigner.presignPutObject(presignRequest);
        return presignedRequest.url().toString();
    }

    /**
     * 构建上传对象预签名请求
     * @param fileName 文件名
     * @param bucketName 桶名
     * @return 上传对象预签名请求
     */
    private PutObjectPresignRequest buildPreSignReq(String fileName, String bucketName) {
        return PutObjectPresignRequest.builder()
                .signatureDuration(Duration.ofSeconds(Constant.S3_URL_DURATION_SECONDS))
                .putObjectRequest(PutObjectRequest.builder()
                        .bucket(bucketName)
                        .key(fileName)
                        .build())
                .build();
    }
}

配置

当然,上面只是实现的代码而已,所以配置在哪配置呢?

答:需要配置挺多地方的

  1. key 和 secret的配置

2.url的配置

2.1 修改文件资源服务器域名

2.2 修改后台vue项目,修改图片域名,也就是管理系统(mall4vs-bbcmall4vp-bbc

开发环境: .env.development

生产环境: .env.production

如图:

# 静态资源文件url
VITE_APP_RESOURCES_URL = 'https://img.mall4j.com/'

2.3 修改uniapp图片域名(mall4uni-bbc

开发环境: .env.development

生产环境: .env.production

# 图片域名
VITE_APP_RESOURCES_URL = 'https://img.mall4j.com/'

2.4 用户pc端,无需修改

nginx配置

虽然普通的文件上传由前端进行上传,但是excel导入的文件上传还是要经过服务器,而nginx的有限制文件上传大小的配置,这时需要配置nginx文件上传大小

client_max_body_size 20m;

spring boot使用tomcat容器的时候要注意

spring boot 使用的web容器为tomcat的时候,每次上传会上传到一个临时的文件夹中,而linux系统会在30天后删除该文件夹,导致文件上传异常。此时需要在配置文件配置临时上传的文件夹

我们在application.yml指定了这个文件夹为linux系统的默认临时文件夹,解决了这个问题。

server:
  tomcat:
    basedir: /temp