阿里云OSS文件上传实现思路以及实现方案(后端实现)

278 阅读5分钟

阿里云文件上传的作用

支持图片、视频、文档等任意类型文件存储,典型应用场景:比如用户头像存储····以下案例也是基于这个来讲解,。

步骤1:登录阿里云,创建一个bucket(简略的说一说)

点击这里->阿里云

接下来:点击右上角的控制台,然后搜索对象存储OSS,然后会看到创建一个bucket,创建的时候输入bucket名字,存储冗余类型选择本地冗余类型,读写权限暂时不用改,然后直接创建。然后在阻止公共访问那里取消这个选项,然后在读写权限那里修改为公共读,然后在右上角头像,点击AccessKey,创建一个accessKey,然后经过一系列验证会得到两个东西,一个AccessKey ID,和AccessKey Secret,这两个相当于一个身份凭证吧。这样一个bucket就创建好了。比如一个图片传过来给bucket,会得到一个地址,这个地址就是可以让浏览器找到这个图片的

步骤2:配置环境变量

在高级系统设置里面的环境变量里面配置上面的用户变量: OSS_ACCESS_KEY_ID=xxxxxx OSS_ACCESS_KEY_SECRET=xxxxxxx

然后接下来是在java项目里面配置如何将前端传过来的图片文件存入刚刚创建的bucket的,并且返回一个url。

步骤3:引入OSS SDK的依赖

<!--阿里云OSS文件上传-->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>${oss}</version>
</dependency>

步骤4:application.yml文件配置基本信息

spring:
  alioss:
    endpoint: 这个在bucket列表的概览里面往下滑能看到
    access-key-id: 你自己的id
    access-key-secret: 你自己的密钥
    bucket-name: bucket名字

步骤5:创建一个实体类AliOssProperties

用于封装刚刚的配置文件里的数据,方便待会拿来直接用

@Data @Component @ConfigurationProperties(prefix = "spring.alioss") public class AliOssProperties { String endpoint; String accessKeyId; String accessKeySecret; String bucketName; }

@Data
@Component
@ConfigurationProperties(prefix = "spring.alioss")
public class AliOssProperties {
     String endpoint;
     String accessKeyId;
     String accessKeySecret;
     String bucketName;
}

@ConfigurationProperties(prefix = "spring.alioss")这个注解的意思就是去配置文件找这个路径下对应的参数,配置文件单词之间虽然是-分隔,但是会自动映射到驼峰命名的。

步骤6:创建一个工具类AliOssUtil(核心)

@Data
@AllArgsConstructor
@Slf4j
public class AliOssUtil {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
 
 
    public String upload(byte[] bytes, String objectName) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 创建PutObject请求。
            ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes));
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }

        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

        log.info("文件上传到:{}", stringBuilder.toString());

        return stringBuilder.toString();
    }
}

代码有点长,但都是一些固定逻辑,参数:传入图片文件的字节数组,还有一个文件在bucket的名字,第一步,使用OSS Java SDK创建OSSClient客户端,使用这个客户端发出一个请求,参数都有bucket的名字,存入文件的名字,还有个字节流,catch都是一些捕获到异常输出的一些东西,finally就是释放资源。然后就是创建一个url,上面说了,将图片存储到bucket里面会有一个url返回,这里用StringBuilder构建,节省资源。最后返回这个url字符串。之后前端会将这个字符串进行处理,然后让后端利用数据库存储,到查询的时候就会利用这个url显示图片。

步骤7:将这个AliOSSUtil放入IOC容器

这里是通过bean注解来注入

@Configuration
@Slf4j
public class OssConfiguration {

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

这里是创建一个配置类,在springboot项目启动的时候,会加载这个配置类,被bean注解修饰的就会依赖注入,这里主要是工具类里面要用到那四个属性 endpoint,accessKeyId,accessKeySecret,bucketName,这里通过构造方法使依赖注入的这个工具类的这四个变量都带有刚刚配置文件的值。

步骤8:创建一个Controller来实现前端上传文件的时候来接收。

@RequestMapping("/file")
@RestController
public class FileUploadController {

    @Autowired
    private AliOssUtil aliOssUtil; // 注入工具类

    @PostMapping("/upload")
    public Result<String> uploadImage(
            @RequestParam("image") MultipartFile image,  // 接收文件
            @RequestParam(value = "prefix", required = false) String customPrefix) {

        try {
            // 1. 校验文件
            if (image.isEmpty()) {
                return Result.error("文件不能为空");
            }
            // 2. 生成唯一文件名(防止覆盖)
            // 生成唯一文件名:UUID + 原始文件后缀
            String originalFilename = image.getOriginalFilename();
            String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String objectName = "images/" + UUID.randomUUID() + fileExtension;

            // 3. 上传到OSS
            String url = aliOssUtil.upload(image.getBytes(), objectName);
            return Result.success(url);
        } catch (Exception e) {
            return Result.error(e.getMessage());
        }
    }
}

注解@RequestParam("image") MultipartFile image接收一个文件名为image的文件,下面那个注解可有可无,然后校验文件,判断是否是空文件,然后拿到原始的文件名,通过原始的文件名来获得后缀,有可能是jpg,可能png,然后通过UUID生成一个唯一的文件名,因为一个bucket里面不能有同名文件。然后返回这个url。

讨论:

其实一开始我觉得配置四个属性 endpoint,accessKeyId,accessKeySecret,bucketName有点多余了,因为直接放在工具类里面的时候也能直接使用,没必要创建一个实体类来存和放到配置文件里,但是看了看别人的看法的时候,这样做是有必要的,这样项目维护的时候就不用去翻代码,而是直接修改配置文件就行了,挺方便的。

以上就是一个简单的阿里云图片上传的实现思路以及代码,希望对大家有用,有什么不足之处还希望各位指点一下。