Springboot整合OSS实现文件上传

阿里云对象存储服务(Object Storage Service,简称
OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。OSS可用于图片、音视频、日志等海量文件的存储。各种终端设备、Web网站程序、移动应用可以直接向OSS写入或读取数据。

OSS中的相关概念

  • Endpoint:访问域名,通过该域名可以访问OSS服务的API,进行文件上传、下载等操作。
  • Bucket:存储空间,是存储对象的容器,所有存储对象都必须隶属于某个存储空间。
  • Object:对象,对象是 OSS 存储数据的基本单元,也被称为 OSS 的文件。
  • AccessKey:访问密钥,指的是访问身份验证中用到的 AccessKeyId 和 AccessKeySecret。

1)创建Springboot项目,并在pom.xml中添加相关依赖

<!-- OSS SDK 相关依赖 -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
            <version>2.5.0</version>
		</dependency>

2)在application.yml中添加OSS相关配置

# OSS相关配置信息
aliyun:
  oss:
    endpoint: oss-cn-beijing.aliyuncs.com # oss对外服务的访问域名
    accessKeyId: test # 访问身份验证中用到用户标识
    accessKeySecret: test # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
    bucketName: probe-oss # oss的存储空间
    dir:
      prefix: mall/images/ # 上传文件夹路径前缀

3)创建OssConfig.java,用于配置OSS的连接客户端OSSClient

@Configuration
public class OssConfig {
    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.accessKeyId}")
    private String ALIYUN_OSS_ACCESSKEYID;
    @Value("${aliyun.oss.accessKeySecret}")
    private String ALIYUN_OSS_ACCESSKEYSECRET;
    @Bean
    public OSSClient ossClient(){
        return new OSSClient(ALIYUN_OSS_ENDPOINT,ALIYUN_OSS_ACCESSKEYID,ALIYUN_OSS_ACCESSKEYSECRET);
    }
}

4)添加图片上传状态的实体类和枚举类

FileStateEnum

public enum FileStateEnum {
    GET_FILE_FAIL(-1,"获取文件流失败"),GET_FILE_SUCCESS(1,"成功获取文件流ccc"),
    NULL_FILE(-1,"上传文件为空"),MAX_SIZE_FILE(-1,"上传图片大小不能超过10M"),
    UPLOAD_FILE_FAIL(-1,"上传文件失败"),UPLOAD_FILE_SUCCESS(1,"上传文件成功"),
    DELETE_FILE_FAIL(-1,"删除文件失败");

    private int state;
    private String stateInfo;

    FileStateEnum(int state, String stateInfo) {
        this.state = state;
        this.stateInfo = stateInfo;
    }

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
    }

    public String getStateInfo() {
        return stateInfo;
    }

    public void setStateInfo(String stateInfo) {
        this.stateInfo = stateInfo;
    }
}

ImageHolder

@Data
public class ImageHolder {
    private FileStateEnum StateEnum;
    private String fileName;
    private MultipartFile multipartFile;
    private List<MultipartFile> list;

    //成功的构造器
    public ImageHolder(FileStateEnum stateEnum, MultipartFile multipartFile) {
        StateEnum = stateEnum;
        this.multipartFile = multipartFile;
    }
    public ImageHolder(FileStateEnum stateEnum, String fileName) {
        StateEnum = stateEnum;
        this.fileName = fileName;
    }

    //失败的构造器
    public ImageHolder(FileStateEnum stateEnum) {
        StateEnum = stateEnum;
    }
}

5)添加OSS业务接口OssService,到时候只需在Controller层获取表单传过来的MultipartFile,然后调用service接口的方法即可实现文件上传功能

/**
 * oss上传管理Service
 *
 */
public interface OssService {
    FileStateEnum addHeadImage(MultipartFile file);
}

6)添加OSS业务接口OssService的实现类OssServiceImpl

/**
 * oss上传管理Service实现类
 */
@Service
public class OssServiceImpl implements OssService {

    @Value("${aliyun.oss.bucketName}")
    private String ALIYUN_OSS_BUCKET_NAME;
    @Value("${aliyun.oss.endpoint}")
    private String ALIYUN_OSS_ENDPOINT;
    @Value("${aliyun.oss.dir.prefix}")
	private String ALIYUN_OSS_DIR_PREFIX;

    //图片URL过期时间为10年  3600l* 1000*24*365*10
    private final long EXPIRATION = 36001 * 1000 * 24 * 365 * 10;

    @Autowired
    private OSSClient ossClient;
    
    /**
     * 上传一张图片到阿里云OSS中
     * @param file 需要上传的图片输入流
     * @return
     */
    @Override
    @Transactional
    public FileStateEnum addHeadImage(MultipartFile file) {
        //上传图片到阿里云中并返回成功上传后的图片名
        ImageHolder holder = addHeadImageToOss(file,ALIYUN_OSS_DIR_PREFIX);
        if (holder.getStateEnum().getState()>0){
            //如果需要获取上传后图片的URL,则调用该方法即可
            //String imgUrl = getImageUrl(holder.getFileName(),ALIYUN_OSS_DIR_PREFIX);
            return FileStateEnum.UPLOAD_FILE_SUCCESS;
        }else {
            return FileStateEnum.UPLOAD_FILE_FAIL;
        }
    }

    
    /**
     * 获取成功上传后文件的url
     * @param fileName 文件名
     * @param dirPre 上传文件的所在路径
     * @return
     */
    private String getImageUrl(String fileName,String dirPre) {
        String imgUrl = "";
        if (!StringUtils.isEmpty(fileName)){
            String[] split = fileName.split("/");
            String key = dirPre + split[split.length-1];
            Date expiration =  new Date(System.currentTimeMillis() + EXPIRATION);
            //生成URL
            URL url = ossClient.generatePresignedUrl(ALIYUN_OSS_BUCKET_NAME,key,expiration);
            if (null != url){
                imgUrl = url.toString();
            }
        }
        return "".equals(imgUrl)?imgUrl:imgUrl.substring(0,imgUrl.indexOf("?"));
    }

    /**
     * 上传至OSS中并返回新生成的文件名
     * @param file 需要上传的文件图片
     * @return
     */
    private ImageHolder addHeadImageToOss(MultipartFile file,String filePath) {
        String fileName = null;
        InputStream instream = null;
        try {
            //根据原始文件名随机生成新的文件名
            fileName = getRandomName(file.getOriginalFilename());
            instream = file.getInputStream();
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(instream.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getContentType(fileName.substring(fileName.lastIndexOf("."))));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectResult putResult = ossClient.putObject(ALIYUN_OSS_BUCKET_NAME, filePath + fileName, instream, objectMetadata);
        } catch (IOException e) {
            return new ImageHolder(FileStateEnum.UPLOAD_FILE_FAIL);
        } finally {
            try {
                if (null != instream){
                    instream.close();
                }
            }catch (IOException e){
                return new ImageHolder(FileStateEnum.UPLOAD_FILE_FAIL);
            }
        }
        return new ImageHolder(FileStateEnum.UPLOAD_FILE_SUCCESS,fileName);
    }

    /**
     * 随机生成文件名
     * @param originalFileName 原始的文件名
     * @return
     */
    private String getRandomName(String originalFileName) {
        //获取文件的后缀名
        String subString = originalFileName.substring(originalFileName.lastIndexOf("."))
                .toLowerCase();
        Random random = new Random();
        return random.nextInt(10000) + System.currentTimeMillis() + subString;
    }

    /**
     * 判断OSS服务文件上传时文件的类型contentType
     * @param fileNameExtension
     * @return
     */
    private String getContentType(String fileNameExtension){
        if (fileNameExtension.equalsIgnoreCase(".bmp")) {
            return "image/bmp";
        }
        if (fileNameExtension.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (fileNameExtension.equalsIgnoreCase(".jpeg") ||
                fileNameExtension.equalsIgnoreCase(".jpg") ||
                fileNameExtension.equalsIgnoreCase(".png")) {
            return "image/jpeg";
        }
        if (fileNameExtension.equalsIgnoreCase(".html")) {
            return "text/html";
        }
        if (fileNameExtension.equalsIgnoreCase(".txt")) {
            return "text/plain";
        }
        if (fileNameExtension.equalsIgnoreCase(".vsd")) {
            return "application/vnd.visio";
        }
        if (fileNameExtension.equalsIgnoreCase(".pptx") ||
                fileNameExtension.equalsIgnoreCase(".ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (fileNameExtension.equalsIgnoreCase(".docx") ||
                fileNameExtension.equalsIgnoreCase(".doc")) {
            return "application/msword";
        }
        if (fileNameExtension.equalsIgnoreCase(".xml")) {
            return "text/xml";
        }
        return "image/jpg";
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_43517302/article/details/106465672