springboot 阿里云oss图片上传和异常处理

自己去申请开通阿里云oss。

对象存储 OSS_云存储服务_企业数据管理_存储-阿里云

1.在pom.xml添加依赖

        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>3.14.0</version>
        </dependency>

 2.在application.yml 加入OSS配置值

aliyun:
  oss:
    # oss对外服务的访问域名
    endpoint: oss-cn-xxxxx.aliyuncs.com
    # 访问身份验证中用到用户标识(填自己的)
    accessKeyId: xxxxxx
    # 用户用于加密签名字符串和oss用来验证签名字符串的密钥(填自己的)
    accessKeySecret: xxxxxx
    # oss的存储空间
    bucketName: xxxxx
    # 上传文件大小(M)
    maxSize: 3
    # 上传文件夹路径前缀
    dir:
      prefix: xxxxxx/

3.在项目的包config创建配置类OssConfig.java

package com.xxxx.config;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 阿里云OSS配置信息
 */
@Configuration
public class OssConfig {

    @Value("${aliyun.oss.endpoint}")
    String endpoint;

    @Value("${aliyun.oss.accessKeyId}")
    String accessKeyId;

    @Value("${aliyun.oss.accessKeySecret}")
    String accessKeySecret;

    @Bean
    public OSSClient createOssClient() {
        return (OSSClient) new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
}

4. 在控制层 上传图片,新建UploadController.java

package com.xxxx.controller;

/**
 * 阿里云Oss上传图片
 */
@RestController
public class UploadController {

    @Value("${aliyun.oss.bucketName}")
    private String bucketName;

    @Value("${aliyun.oss.dir.prefix}")
    private String dirPrefix;

    @Resource
    private OSSClient ossClient;

    
    //允许上传的格式 可以自己增加上传文件格式
    private static final String[] IMAGE_TYPE = new String[]{".jpg", ".jpeg", ".gif", ".png"};

    @PostMapping("/upload")
    public ApiRestResponse upload(@RequestParam("photo") MultipartFile file) {
        //在这里写判断file isEmpty是无效的,压根进不去,之间就被拦截异常了
        //if(file.isEmpty()){....}
        //写file.getSize()也是无效的

        boolean bol = assessFileType(file);
        if (!bol) {
            return ApiRestResponse.error(400, "上传格式不对~");
        }
        String url = "";
        try {

            InputStream inputStream = file.getInputStream();
            //整理文件名称
            String fileName = getFileName(file);
            //创建PutObject请求
            PutObjectResult result = ossClient.putObject(bucketName, fileName, inputStream);
            System.out.println(result);

            //关闭OOSClient
            //ossClient.shutdown();

            //返回完整路径给前端
            url = "https://" + bucketName + "." + ossClient.getEndpoint().getHost() + "/" + fileName;
        } catch (IOException e) {
            return ApiRestResponse.error(400, "上传失败~");
        }
        return ApiRestResponse.success(url);
    }

    /**
     * 整理上传 文件名称 和 路径
     * @param file
     * @return
     */
    private String getFileName(MultipartFile file) {
        // 文件后缀
        String suffixName = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf("."));
        //文件名称
        String fileName = UUID.randomUUID().toString() + suffixName;

        //当前年月日
        String loalYmd = DateTimeUtil.localYmd();
        String path = dirPrefix + loalYmd + "/" + fileName;

        return path;
    }

    /**
     * 判断文件格式
     */
    private boolean assessFileType(MultipartFile file) {
        //对图片的后缀名做校验
        boolean isPass = false;
        for (String type : IMAGE_TYPE) {
            if (StringUtils.endsWithIgnoreCase(file.getOriginalFilename(), type)) {
                isPass = true;
                break;
            }
        }
        return isPass;
    }
}

5. 需要注意的是,如果上传图片为空,或者 上传图片过大。后端控制台会直接报错。比如:

上传图片是空的

控制台报:因为我异常做了统一封装

异常情况org.springframework.web.multipart.MultipartException: Current request is not a multipart request

 网上的帖子说,给postman的header加content-type为multipart/form-data。

但我测试时,加不加是无所谓的。加了反而又报其他bug。

如果你在控制层,做判断,也不行的

if(file.isEmpty()){
   //图片没上传
}

因为springboot直接就把异常给捕捉了,并返回统一异常

{
    "code": 404,
    "msg": "服务器异常~",
    "data": null
}

6. 还有一个异常是,上传文件过大时报

控制台打印出。 

Maximum upload size exceeded; nested exception is 
java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: 
The field photo exceeds its maximum permitted size of 2097152 bytes.

网上的说法都是tomcat已经默认允许你只上传1M的文件,但我这里是2M的。

但我oss配置的最大文件不是3M吗?

 然后在application.yml写配置,在server怎么写,控制台永远都是1M的

 应该在spring写配置

7.最后怎么让前端能正确返回异常消息呢?

    /**
     * 处理文件上传大小超限制
     */
    @ExceptionHandler(MultipartException.class)
    @ResponseBody
    public ApiRestResponse fileUploadExceptionHandler(MultipartException e) {
        log.error("上传文件异常:", e);
        if (e.getRootCause() instanceof org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException) {
           
            return ApiRestResponse.error(400, "上传文件不能超过2M");

        }else if(e.getRootCause() instanceof org.apache.tomcat.util.http.fileupload.impl.SizeLimitExceededException){
            
            return ApiRestResponse.error(400, "上传文件异常");
        }
        return ApiRestResponse.error(400, "上传文件不存在或异常");
    }

8.异常返回

9.正确返回

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值