对象存储(OSS)使用指南

一、阿里云OSS集成

步骤一:创建阿里云OSS账号

在开始集成阿里云OSS之前,确保您已在阿里云官网注册了账号,并创建了一个OSS存储空间(Bucket)。具体操作步骤可参考阿里云官方文档。

步骤二:获取AccessKeyId和AccessKeySecret

  1. 登录阿里云控制台。
  2. 前往 “访问控制” > “用户管理”
  3. 创建一个新的Access Key,记录下AccessKeyIdAccessKeySecret,这些将用于Java应用程序的身份验证。

步骤三:添加阿里云OSS SDK依赖

在您的Java项目中添加阿里云OSS SDK的依赖。您可以使用Maven或Gradle等构建工具。以下是Maven的示例:

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>${aliyun.sdk.oss}</version>
</dependency>

确保在pom.xml中定义了${aliyun.sdk.oss}的具体版本号,例如3.13.2

步骤四:编写AliOssUtil工具类

创建一个配置类用于管理阿里云OSS的相关属性:

package com.example.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import lombok.Data;
import javax.validation.constraints.NotNull;

@Component
@ConfigurationProperties(prefix = "sky.alioss")
@Data
public class AliOssProperties {

    @NotNull
    private String endpoint;

    @NotNull
    private String accessKeyId;

    @NotNull
    private String accessKeySecret;

    @NotNull
    private String bucketName;
}

接着,编写AliOssUtil工具类,用于处理文件上传逻辑:

package com.example.util;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.ClientException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {

    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;

    /**
     * 文件上传
     *
     * @param bytes      文件字节数组
     * @param objectName 文件在OSS中的名称
     * @return 文件访问路径
     */
    public String upload(byte[] bytes, String objectName) {
        try (OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret)) {
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException oe) {
            log.error("OSSException: {}", oe.getErrorMessage());
            // 根据需要重新抛出异常或返回特定的错误信息
        } catch (ClientException ce) {
            log.error("ClientException: {}", ce.getMessage());
            // 根据需要重新抛出异常或返回特定的错误信息
        }

        String fileUrl = String.format("https://%s.%s/%s", bucketName, endpoint, objectName);
        log.info("文件上传到: {}", fileUrl);
        return fileUrl;
    }
}

步骤五:编写阿里云OSS接口代码

创建一个配置类,将AliOssUtil注入为Bean:

package com.example.config;

import com.example.util.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;

@Configuration
@Slf4j
public class OssConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties){
        log.info("开始创建阿里云文件上传工具类对象,{}", aliOssProperties);
        return new AliOssUtil(
                aliOssProperties.getEndpoint(),
                aliOssProperties.getAccessKeyId(),
                aliOssProperties.getAccessKeySecret(),
                aliOssProperties.getBucketName()
        );
    }
}

接下来,编写控制器类,提供文件上传接口:

package com.example.controller;

import com.example.util.AliOssUtil;
import com.example.common.Result;
import com.example.constant.MessageConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.UUID;

@RestController
@RequestMapping("/admin/common/")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {

    @Autowired
    private AliOssUtil aliOssUtil;

    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(@RequestParam("file") MultipartFile file){
        log.info("文件上传,{}", file.getOriginalFilename());
        if (file.isEmpty()) {
            return Result.error("文件不能为空");
        }
        try {
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String objectName = UUID.randomUUID().toString() + extension;
            String filePath = aliOssUtil.upload(file.getBytes(), objectName);
            if (filePath != null) {
                return Result.success(filePath);
            } else {
                return Result.error(MessageConstant.UPLOAD_FAILED);
            }
        } catch (IOException e) {
            log.error("文件上传失败,{}", e.getMessage());
        }
        return Result.error(MessageConstant.UPLOAD_FAILED);
    }
}

二、七牛云OSS集成

步骤一:添加七牛云OSS SDK依赖

在Java项目中添加七牛云OSS SDK的依赖。以下是Maven的示例:

<dependency>
    <groupId>com.qiniu</groupId>
    <artifactId>qiniu-java-sdk</artifactId>
    <version>7.7.0</version>
</dependency>

同时,确保引入七牛云SDK所需的第三方库:

<dependencies>
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>3.14.2</version>
    </dependency>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.5</version>
    </dependency>
    <dependency>
        <groupId>com.qiniu</groupId>
        <artifactId>happy-dns-java</artifactId>
        <version>0.1.6</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
</dependencies>

步骤二:编写七牛云OSS上传逻辑

首先,配置七牛云OSS的相关属性。在application.yml中添加:

sky:
  qiniuoss:
    accessKey: pcd2zT**205L**c8492a86Z**Oeov***XO7WO***
    secretKey: Bu-rtiGv**Krb***gPD3ARSlJoXKe3P***Lags-w
    bucket: your-bucket-name
    domain: http://your-domain.com

接下来,编写上传服务接口及其实现类:

上传服务接口

package com.example.service;

import org.springframework.web.multipart.MultipartFile;

public interface UploadService {
    String upload(MultipartFile file);
}

上传服务实现类

package com.example.service.impl;

import com.example.service.UploadService;
import com.google.gson.Gson;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;

@Service
@ConfigurationProperties(prefix = "sky.qiniuoss")
@Data
@Slf4j
public class UploadServiceImpl implements UploadService {

    private String accessKey;
    private String secretKey;
    private String bucket;
    private String domain;

    private UploadManager uploadManager;
    private Auth auth;

    @PostConstruct
    public void init() {
        Configuration cfg = new Configuration(Region.autoRegion());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;
        this.uploadManager = new UploadManager(cfg);
        this.auth = Auth.create(accessKey, secretKey);
    }

    @Override
    public String upload(MultipartFile file) {
        if (file.isEmpty()) {
            log.error("上传文件为空");
            return null;
        }

        String originalFilename = file.getOriginalFilename();
        String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        String filePath = UUID.randomUUID().toString() + extension;

        return uploadOss(file, filePath);
    }

    private String uploadOss(MultipartFile img, String filePath) {
        String key = filePath;
        try (InputStream inputStream = img.getInputStream()) {
            String upToken = auth.uploadToken(bucket);
            Response response = uploadManager.put(inputStream, key, upToken, null, null);
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            String fileUrl = String.format("%s/%s", domain, putRet.key);
            log.info("文件上传成功: {}", fileUrl);
            return fileUrl;
        } catch (QiniuException ex) {
            Response r = ex.response;
            log.error("七牛云上传异常: {}", r.toString());
            try {
                log.error("七牛云响应: {}", r.bodyString());
            } catch (QiniuException ex2) {
                // 忽略
            }
        } catch (IOException e) {
            log.error("文件读取异常: {}", e.getMessage());
        }
        return null;
    }
}

控制器类

package com.example.controller;

import com.example.service.UploadService;
import com.example.common.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/admin/common/")
@Api(tags = "通用接口")
@Slf4j
public class CommonController {

    @Autowired
    private UploadService uploadService;

    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(@RequestParam("file") MultipartFile file){
        log.info("文件上传,{}", file.getOriginalFilename());
        if (file.isEmpty()) {
            return Result.error("文件不能为空");
        }
        String filePath = uploadService.upload(file);
        if (filePath != null) {
            return Result.success(filePath);
        } else {
            return Result.error("文件上传失败");
        }
    }
}

三、其他事项

统一配置管理

在不同的OSS集成部分,使用统一的配置文件格式和命名规范。例如,阿里云OSS使用sky.alioss前缀,七牛云OSS使用sky.qiniuoss前缀。这样可以保持配置的一致性和可维护性。

sky:
  alioss:
    endpoint: your-alibaba-endpoint
    accessKeyId: your-access-key-id
    accessKeySecret: your-access-key-secret
    bucketName: your-bucket-name
  qiniuoss:
    accessKey: your-qiniu-access-key
    secretKey: your-qiniu-secret-key
    bucket: your-qiniu-bucket
    domain: http://your-qiniu-domain.com

错误处理和日志记录

在上传文件时,详细记录错误信息,以便于调试和维护。确保在所有异常捕获块中记录足够的信息,并根据需要采取相应的处理措施。

安全性考虑

  • 敏感信息保护:确保application.ymlapplication.properties文件中不直接暴露敏感信息(如accessKeysecretKey)。可以使用环境变量、加密配置或配置管理工具(如Spring Cloud Config)来增强安全性。

  • 权限管理:为不同的服务和用户分配最小权限,避免过度授权。

统一接口抽象

如果未来需要支持更多的OSS提供商,可以考虑定义一个统一的上传接口,并为每个OSS提供商实现该接口。这有助于代码的扩展和维护。

public interface OssService {
    String upload(MultipartFile file);
}

@Service
public class AliOssServiceImpl implements OssService {
    // 实现阿里云OSS的上传逻辑
}

@Service
public class QiniuOssServiceImpl implements OssService {
    // 实现七牛云OSS的上传逻辑
}

通过依赖注入,您可以在控制器中灵活选择使用哪种OSS服务。

接口参数校验

使用注解如@Valid和自定义验证注解,确保上传的文件符合预期的格式和大小。

@PostMapping("/upload")
@ApiOperation("文件上传")
public Result<String> upload(@RequestParam("file") @NotNull @Size(max = 5 * 1024 * 1024) MultipartFile file){
    // 上传逻辑
}

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值