阿里云存储OSS

93 阅读3分钟

使用SDK访问OSS

确认常量:

endpoint(外网访问):oss-cn-beijing.aliyuncs.com
bucketName:college-file-210208
用户登录名称 210208@1620937938245015.onaliyun.com
AccessKeyID: LTAI5t5pe4vDtkSr5Sg7ScAU
AccessKeySecret: OsIBpe186YbAuF1l3pPbBTXewJR1hD

新建云存储微服务

pom.xml

<parent>
    <artifactId>service</artifactId>
    <groupId>com.jun</groupId>
    <version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>service_oss</artifactId> <!--阿里云oss api接口服务-->

<dependencies>
    <!--aliyunOSS-->
    <dependency>
        <groupId>com.aliyun.oss</groupId>
        <artifactId>aliyun-sdk-oss</artifactId>
    </dependency>
</dependencies>

application.yml

server:
  port: 8120 # 服务端口

spring:
  profiles:
    active: dev # 环境设置
  application:
    name: service-oss # 服务名

aliyun:
  oss:
    endpoint: 你的endponit
    keyid: 你的阿里云keyid
    keysecret: 你的阿里云keysecret
    #bucket可以在控制台创建,也可以使用java代码创建,注意先测试bucket是否已被占用
    bucketname: guli-file   

启动类

// package com.jun.guli.service.oss;

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) //取消数据源自动配置
@ComponentScan({"com.jun.guli"})
// @EnableDiscoveryClient
public class ServiceOssApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceOssApplication.class, args);
    }
}

可能出现的错误

  • 不添加exclude会出现如下错误:

截图_20225312025321.png

  • 原因:jdbc依赖引入项目后,springboot的自动配置试图在配置文件中查找jdbc相关配置
  • 解决方案:主类上添加注解exclude属性,禁用jdbc自动配置@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

实现文件上传

1.从配置文件读取常量

// package com.jun.guli.service.oss.util;

@Data
@Component
//注意prefix要写到最后一个 "." 符号之前
@ConfigurationProperties(prefix = "aliyun.oss")
public class OssProperties {
    private String endpoint;
    private String bucketname;
    private String keyid;
    private String keysecret;
}

2.FileService.java

// package com.jun.guli.service.oss.service;

public interface FileService {
    // 文件上传至阿里云:输入流、文件夹名称、原始文件名、返回值:文件在oss服务器上的url地址
    String upload(InputStream inputStream, String module, String originalFilename);

    // 2.阿里云文件删除,参数为文件的url地址
    void removeFile(String url);
}

3.FileServiceImpl.java

// package com.jun.guli.service.oss.service.impl;

@Service
public class FileServiceImpl implements FileService {
    @Autowired
    private OssProperties ossProperties;

    @Override
    public String upload(InputStream inputStream, String module, String originalFilename) {
        //读取配置信息
        String endpoint = ossProperties.getEndpoint();
        String keyid = ossProperties.getKeyid();
        String keysecret = ossProperties.getKeysecret();
        String bucketname = ossProperties.getBucketname();

        //判断oss实例是否存在:如果不存在则创建,如果存在则获取
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyid, keysecret);
        if (!ossClient.doesBucketExist(bucketname)) {
            //创建bucket
            ossClient.createBucket(bucketname);
            //设置oss实例的访问权限:公共读
            ossClient.setBucketAcl(bucketname, CannedAccessControlList.PublicRead);
        }

        //构建objectName:
        //构建日期路径:avatar/2020/02/26/文件名
        String folder = new DateTime().toString("yyyy/MM/dd");

        //文件名:uuid.扩展名
        String fileName = UUID.randomUUID().toString();
        String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        String key = module + "/" + folder + "/" + fileName + fileExtension;

        //文件上传至阿里云
        ossClient.putObject(ossProperties.getBucketname(), key, inputStream);

        // 关闭OSSClient。
        ossClient.shutdown();

        //返回url地址
        return "https://" + bucketname + "." + endpoint + "/" + key;
    }

    // 2.删除讲师头像
    @Override
    public void removeFile(String url) {
        String endpoint = ossProperties.getEndpoint();
        String keyid = ossProperties.getKeyid();
        String keysecret = ossProperties.getKeysecret();
        String bucketname = ossProperties.getBucketname();

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyid, keysecret);

        // https://guli-file-220115.oss-cn-beijing.aliyuncs.com/
        String host = "https://" + bucketname + "." + endpoint + "/";
        String objectName = url.substring(host.length());

        // 删除文件。
        ossClient.deleteObject(bucketname, objectName);

        // 关闭OSSClient。
        ossClient.shutdown();
    }
}
删除讲师头像需要OpenFeign

4.FileController.java

// package com.jun.guli.service.oss.controller.admin;

@Api(description="阿里云文件管理")
@Slf4j
@RestController
@RequestMapping("/admin/oss/file")
// @CrossOrigin //跨域
public class FileController {
    @Autowired
    private FileService fileService;

    // 文件上传
    @ApiOperation("文件上传")
    @PostMapping("upload")
    public R upload(
            @ApiParam(value = "文件", required = true)
            @RequestParam("file") MultipartFile file,

            @ApiParam(value = "模块", required = true)
            @RequestParam("module") String module){ //module表示文件夹

        try {
            InputStream inputStream = file.getInputStream();
            String originalFilename = file.getOriginalFilename();
            String uploadUrl = fileService.upload(inputStream, module, originalFilename);
            //返回r对象
            return R.ok().message("文件上传成功").data("url", uploadUrl);
        } catch (Exception e) {
            log.error(ExceptionUtils.getMessage(e)); //将错误跟踪日志用日志记录器打印出来
            //抛出自定义异常,此异常在controller层抛出的时候,会来到GlobalExceptionHandler进行异常捕获。
            throw new GuliException(ResultCodeEnum.FILE_UPLOAD_ERROR);
        }
    }

    @ApiOperation(value = "测试")
    @GetMapping("test")
    public R test() {
        log.info("oss test被调用");
        //模拟长流程的业务
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return R.ok();
    }

    // 删除文件
    @ApiOperation("文件删除")
    @DeleteMapping("remove")
    public R removeFile(
            @ApiParam(value = "要删除的文件路径", required = true)
            @RequestBody String url) {

        fileService.removeFile(url);
        return R.ok().message("文件刪除成功");
    }
}
  • 通过:http://localhost:8120/swagger-ui.html测试接口

自定义异常

GuliException.java

// package com.jun.guli.service.base.exception;

@Data
public class GuliException extends RuntimeException { //项目中的自定义异常一般定义为运行时异常,因为运行时异常是一个非检查型异常。
    //状态码
    private Integer code;

    // 接受状态码和消息
    public GuliException(Integer code, String message) {
        super(message);
        this.code=code;
    }

    // 接收枚举类型
    public GuliException(ResultCodeEnum resultCodeEnum) {
        super(resultCodeEnum.getMessage());
        this.code = resultCodeEnum.getCode();
    }

    @Override
    public String toString() {
        return "GuliException{" +
                "code=" + code +
                ", message=" + this.getMessage() +
                '}';
    }
}

GlobalExceptionHandler.java

// package com.jun.guli.service.base.handler;

@ControllerAdvice  //统一异常处理器,这个注解的作用是作为一个切面,专门处理系统中的错误信息
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class) //异常处理器
    @ResponseBody //返回的错误信息是JSON格式的
    public R error(Exception e){ //出现错误通过异常处理方法返回,而不是通过controller层返回
//        e.printStackTrace();
//        log.error(e.getMessage());
        log.error(ExceptionUtils.getMessage(e));
        return R.error();
    }

    @ExceptionHandler(BadSqlGrammarException.class) //处理特定的异常
    @ResponseBody
    public R error(BadSqlGrammarException e){
//        e.printStackTrace();
//        log.error(e.getMessage());
        log.error(ExceptionUtils.getMessage(e));
        return R.setResult(ResultCodeEnum.BAD_SQL_GRAMMAR);
    }

    @ExceptionHandler(HttpMessageNotReadableException.class) //JSON解析异常
    @ResponseBody
    public R error(HttpMessageNotReadableException e){
        e.printStackTrace();
//        log.error(e.getMessage());
        log.error(ExceptionUtils.getMessage(e));
        return R.setResult(ResultCodeEnum.JSON_PARSE_ERROR);
    }

    // 自定义异常
    @ExceptionHandler(GuliException.class)
    @ResponseBody
    public R error(GuliException e){
        log.error(ExceptionUtils.getMessage(e));
        return R.error().message(e.getMessage()).code(e.getCode());
    }
}