IDEA阿里云OSS实现文件上传·解决苍穹外卖图片回显

发布于:2024-07-12 ⋅ 阅读:(219) ⋅ 点赞:(0)

简单交代配置阿里云OSS的思路

1. 首先去阿里云开通一个OSS服务,配置好一个自己的Bucket

2. 在IDEA配置Bucket

3. 拷贝官网的OSS工具类代码

package com.sky.utils;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
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
     * @return
     */
    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();
            }
        }

        //文件访问路径规则 https://BucketName.Endpoint/ObjectName
        StringBuilder stringBuilder = new StringBuilder("https://");
        stringBuilder
                .append(bucketName)
                .append(".")
                .append(endpoint)
                .append("/")
                .append(objectName);

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

        return stringBuilder.toString();
    }
}

4. OSS工具类对象的创建

package com.sky.config;

import com.sky.properties.AliOssProperties;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 配置类,用于创建AliOssUtil对象
 */
@Configuration
@Slf4j
public class OssConfiguration {


    // 通过参数注入的方式,将Oss的配置信息传递进来
    // Bean 如果容器中没有AliOssUtil对象,则创建AliOssUtil对象
    // ConditionalOnBean 表示如果容器中存在AliOssUtil对象,则不创建AliOssUtil对象
    @Bean
    @ConditionalOnMissingBean
    public AliOssUtil aliOssUtil(AliOssProperties aliOssProperties) {
        log.info("开始创建阿里云文件上传工具类对象:{}",aliOssProperties);
        // 创建AliOssUtil对象,并传入配置信息
        return new AliOssUtil(aliOssProperties.getEndpoint(),
                              aliOssProperties.getAccessKeyId(),
                              aliOssProperties.getAccessKeySecret(),
                              aliOssProperties.getBucketName());
    }
}

5. 在Controller层编写文件上传逻辑

// Autowired注解的作用:自动将匹配的Bean装配到@Autowired标注的变量、方法或构造函数上。(依赖注入)
    @Autowired
    private AliOssUtil aliOssUtil;


    /**
     * 文件上传
     * @param file
     * @return
     */
    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(MultipartFile file) {
        log.info("文件上传接口被调用:{}",file);
        String filePath = null;
        try {
            //  获取原始文件名
            String originalFilename = file.getOriginalFilename();
            // 截取原始文件名的扩展名
            String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 生成新的文件名: UUID + 扩展名
            String newFileName = UUID.randomUUID().toString() + extName;

            // 文件上传请求路径
            filePath = aliOssUtil.upload(file.getBytes(), newFileName);
        }catch(IOException e){
            e.printStackTrace();
            log.error("文件上传失败:{}",e);
            return Result.error(MessageConstant.UPLOAD_FAILED);
        }
       return Result.success(filePath);
    }

6. 测试(省略,做到这里基本无误了)

接下来就来讲讲文件回显失败的几点调试方向

文件回显失败的原因及其排查方向

1. 检查你文件上传拼接的url是否正确

这一步如果错了,实际上上传就已经错了,更别提回显这方面的事情了

2. 首先,如果你全程跟着苍穹老师写的代码去做,必然会导致文件回显失败,我记得视频里面的代码最后是没有返回文件上传路径的,你可以改一下再尝试

具体的,苍穹老师写的文件上传代码:

问题就出在成功的时候还封装了错误的信息进行返回,你应该要把错误的返回放到catch中,成功后把文件路径放到Result中

/**
     * 文件上传
     * @param file
     * @return
     */
    @PostMapping("/upload")
    @ApiOperation("文件上传")
    public Result<String> upload(MultipartFile file) {
        log.info("文件上传接口被调用:{}",file);
        try {
            //  获取原始文件名
            String originalFilename = file.getOriginalFilename();
            // 截取原始文件名的扩展名
            String extName = originalFilename.substring(originalFilename.lastIndexOf("."));
            // 生成新的文件名: UUID + 扩展名
            String newFileName = UUID.randomUUID().toString() + extName;

            // 文件上传请求路径
            String filePath  = aliOssUtil.upload(file.getBytes(), newFileName);
        }catch(IOException e){
            e.printStackTrace();
            log.error("文件上传失败:{}",e);
            
        }
       return Result.error(MessageConstant.UPLOAD_FAILED);
    }
3. 接着排查OSS,你得允许你的网页可以访问你的OSS对象存储服务之后才可以拿到文件的访问路径,使用OSS必须设置公共读属性

由于我只是练习程序,不想麻烦所以直接设置了公共读写。但是其实最安全的方式还是配置一个防盗链放行你的网页会比较安全