Springboot集成阿里云OSS

Springboot实现阿里云对象存储OSS文件上传下载



前言

OSS作为阿里巴巴全集团数据存储的核心基础设施,多年支撑双十一业务高峰,历经高可用与高可靠的严苛考验。OSS的多重冗余架构设计,为数据持久存储提供可靠保障。同时,OSS基于高可用架构设计,消除单节故障,确保数据业务的持续性。


一、OSS是什么?

阿里云对象存储服务(Object Storage Service,简称OSS),是阿里云对外提供的海量、安全、低成本、高可靠的云存储服务。您可以通过本文档提供的简单的REST接口,在任何时间、任何地点、任何互联网设备上进行上传和下载数据。基于OSS,您可以搭建出各种多媒体分享网站、网盘、个人和企业数据备份等基于大规模数据的服务。废话不多说,请允许我娓娓道来!

二、使用步骤

1.引入依赖

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

2.AliyunOss工具类


package com.test.api.aliyun;

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import com.test.common.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

@Slf4j
@Component
public class AliyunOss {
    @Value("${aliyun.oss.appKey}")
    private String appKey;
    @Value("${aliyun.oss.appSecret}")
    private String appSecret;
    @Value("${aliyun.oss.endpoint}")
    private String endpoint;
    @Value("${aliyun.oss.endpointInternal}")
    private String endpointInternal;
    @Value("${aliyun.oss.bucketName}")
    private String bucketName;
    @Value("${aliyun.oss.callbackUrl}")
    private String callbackUrl;
    private static final ConcurrentHashMap<String, String> uploadCache = new ConcurrentHashMap<>();
    private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(Integer.MAX_VALUE);

    /**
     * 上传升级包
     * @param fileName
     * @param fileType
     * @param is
     * @param callbackDataMap 回调地址
     * @return
     */
    public boolean uploadFile(String fileName, FileType fileType, InputStream is, Map<String, String> callbackDataMap) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            // 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            OSS ossClient = new OSSClientBuilder().build(endpointInternal, appKey, appSecret, clientBuilderConfiguration);
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, is);
            if (fileType.getCallback() != null) {
                Callback callback = new Callback();
                callback.setCallbackUrl(callbackUrl + fileType.getCallback());
                String messageId = callbackDataMap.get("messageId");
                String sensitivity = callbackDataMap.get("sensitivity");
                String deviceType = callbackDataMap.get("deviceType");
                callback.setCallbackBody("{\\\"messageId\\\":${x:messageId},\\\"sensitivity\\\":${x:sensitivity},\\\"deviceType\\\":${x:deviceType}}");
                callback.setCalbackBodyType(Callback.CalbackBodyType.JSON);
                callback.addCallbackVar("x:messageId", messageId);
                callback.addCallbackVar("x:sensitivity", sensitivity);
                callback.addCallbackVar("x:deviceType", deviceType);
                putObjectRequest.setCallback(callback);

            }
            ossClient.putObject(putObjectRequest);
            ossClient.shutdown();
            return true;
        } catch (Exception e) {
            log.error("上传文件异常:{}", e.getMessage(), e);
        }
        return false;
    }

    /**
     * 上传文件
     * @param fileName
     * @param fileType
     * @param is
     * @return
     */
    public boolean uploadFilePublic(String fileName, FileType fileType, InputStream is) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            // 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            OSS ossClient = new OSSClientBuilder().build(endpointInternal, appKey, appSecret, clientBuilderConfiguration);
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setObjectAcl(CannedAccessControlList.PublicRead);
            ossClient.putObject(bucketName, objectName, is, metadata);
            ossClient.shutdown();
            return true;
        } catch (Exception e) {
            log.error("上传文件异常:{}", e.getMessage(), e);
        }
        return false;
    }

    /**
     * 判断是否存在
     * @param fileName
     * @param fileType
     * @return
     */
    public boolean exists(String fileName, FileType fileType) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            // 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            OSS ossClient = new OSSClientBuilder().build(endpointInternal, appKey, appSecret, clientBuilderConfiguration);
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            ossClient.shutdown();
            return exists;
        } catch (Exception e) {
            log.error("上传文件异常:{}", e.getMessage(), e);
        }
        return false;
    }

    /**
     * 获取上传地址
     * @param fileName
     * @param fileType
     * @param callbackDataMap
     * @return
     */
    public String getUploadUrl(String fileName, FileType fileType, Map<String, Object> callbackDataMap) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            OSS ossClient = new OSSClientBuilder().build(endpoint, appKey, appSecret, clientBuilderConfiguration);
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
            Date expiration = new Date(new Date().getTime() + 5 * 60 * 1000);
            request.setExpiration(expiration);
            request.setContentType("application/octet-stream");
            // 生成PUT方式的签名URL。
            if (callbackDataMap != null && fileType.getCallback() != null) {
                Map<String, String> callback = new HashMap<>();
                callback.put("callbackUrl", callbackUrl + fileType.getCallback());
                callback.put("callbackBody", JsonUtil.toString(callbackDataMap));
                callback.put("callbackBodyType", "application/json");
                String callbackData = Base64.getEncoder().encodeToString(JsonUtil.toString(callback).getBytes(StandardCharsets.UTF_8));
                request.addQueryParameter("callback", callbackData);
            }
            URL signedUrl = ossClient.generatePresignedUrl(request);
            ossClient.shutdown();
            return signedUrl.toString();
        } catch (Exception e) {
            log.error("获取上传地址异常:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取下载地址
     * @param fileName
     * @param fileType
     * @return
     */
    public String getDownloadUrl(String fileName, FileType fileType) {
        try {
            if (StringUtils.isEmpty(fileName)) {
                return null;
            }
            String objectName = fileType.getType().concat("/").concat(fileName);
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            OSS ossClient = new OSSClientBuilder().build(endpoint, appKey, appSecret, clientBuilderConfiguration);
            // 设置URL过期时间为1小时。
            Date expiration = new Date(new Date().getTime() + 5 * 60 * 1000);
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                return null;
            }
            // 生成PUT方式的签名URL。
            URL signedUrl = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            ossClient.shutdown();
            return signedUrl.toString();
        } catch (Exception e) {
            log.error("获取下载地址异常:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取下载地址
     * @param fileName
     * @param fileType
     * @param time
     * @return
     */
    public String getDownloadUrl(String fileName, FileType fileType, int time) {
        try {
            if (StringUtils.isEmpty(fileName)) {
                return null;
            }
            String objectName = fileType.getType().concat("/").concat(fileName);
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            OSS ossClient = new OSSClientBuilder().build(endpoint, appKey, appSecret, clientBuilderConfiguration);
            // 设置URL过期时间为1小时。
            Date expiration = new Date(new Date().getTime() + time);
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                return null;
            }
            // 生成PUT方式的签名URL。
            URL signedUrl = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            ossClient.shutdown();
            return signedUrl.toString();
        } catch (Exception e) {
            log.error("获取下载地址异常:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取下载地址
     * @param fileName
     * @param fileType
     * @return
     */
    public String getDownloadUrlForHttp(String fileName, FileType fileType) {
        try {
            if (StringUtils.isEmpty(fileName)) {
                return null;
            }
            String objectName = fileType.getType().concat("/").concat(fileName);
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            // 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
            OSS ossClient = new OSSClientBuilder().build(endpoint, appKey, appSecret, clientBuilderConfiguration);
            // 设置URL过期时间为1小时。
            Date expiration = new Date(new Date().getTime() + 5 * 60 * 1000);
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                return null;
            }
            // 生成PUT方式的签名URL。
            URL signedUrl = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            ossClient.shutdown();
            return signedUrl.toString();
        } catch (Exception e) {
            log.error("获取下载地址异常:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取上传地址
     * @param fileName
     * @param fileType
     * @param callbackDataMap
     * @return
     */
    public String getUploadUrlForInternal(String fileName, FileType fileType, Map<String, Object> callbackDataMap) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            OSS ossClient = new OSSClientBuilder().build(endpointInternal, appKey, appSecret, clientBuilderConfiguration);
            GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
            Date expiration = new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000);
            request.setExpiration(expiration);
            request.setContentType("application/octet-stream");
            // 生成PUT方式的签名URL。
            if (callbackDataMap != null && fileType.getCallback() != null) {
                Map<String, String> callback = new HashMap<>();
                callback.put("callbackUrl", callbackUrl + fileType.getCallback());
                callback.put("callbackBody", JsonUtil.toString(callbackDataMap));
                callback.put("callbackBodyType", "application/json");
                String callbackData = Base64.getEncoder().encodeToString(JsonUtil.toString(callback).getBytes(StandardCharsets.UTF_8));
                request.addQueryParameter("callback", callbackData);
            }
            URL signedUrl = ossClient.generatePresignedUrl(request);
            ossClient.shutdown();
            return signedUrl.toString();
        } catch (Exception e) {
            log.error("获取上传地址异常:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取下载地址
     * @param fileName
     * @param fileType
     * @return
     */
    public String getDownloadForInternal(String fileName, FileType fileType) {
        try {
            String objectName = fileType.getType().concat("/").concat(fileName);
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            // 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
            OSS ossClient = new OSSClientBuilder().build(endpointInternal, appKey, appSecret, clientBuilderConfiguration);
            // 设置URL过期时间为1小时。
            Date expiration = new Date(new Date().getTime() + 7 * 24 * 60 * 60 * 1000);
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                return null;
            }
            // 生成PUT方式的签名URL。
            URL signedUrl = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
            ossClient.shutdown();
            return signedUrl.toString();
        } catch (Exception e) {
            log.error("获取下载地址异常:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 下载文件
     * @param fileName
     * @param fileType
     * @return
     */
    public ByteArrayOutputStream download(String fileName, FileType fileType) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            String objectName = fileType.getType().concat("/").concat(fileName);
            ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
            clientBuilderConfiguration.setSignatureVersion(SignVersion.V2);
            clientBuilderConfiguration.setSupportCname(true);
            // 用户拿到STS临时凭证后,通过其中的安全令牌(SecurityToken)和临时访问密钥(AccessKeyId和AccessKeySecret)生成OSSClient。
            OSS ossClient = new OSSClientBuilder().build(endpointInternal, appKey, appSecret, clientBuilderConfiguration);
            // 设置URL过期时间为1小时。
            boolean exists = ossClient.doesObjectExist(bucketName, objectName);
            if (!exists) {
                return null;
            }
            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
            IOUtils.copy(ossObject.getObjectContent(), baos);
            ossClient.shutdown();
            return baos;
        } catch (Throwable e) {
            log.error("下载文件异常:{}", e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取绝对路径访问地址
     * @param fileName
     * @param fileType
     * @return
     */
    public String getPublicUrl(String fileName, FileType fileType) {
        try {
            return endpoint + "/" + fileType.type + "/" + fileName;
        } catch (Exception e) {
            log.error("获取访问地址异常:{}", e.getMessage(), e);
        }
        return null;
    }

    public enum FileType {
        TEST("test/test", "测试", "oss/controller/test"),
        ;

        private String type;
        private String desc;
        private String callback;

        FileType(String type, String desc, String callback) {
            this.type = type;
            this.desc = desc;
            this.callback = callback;
        }

        public String getType() {
            return type;
        }

        public String getDesc() {
            return desc;
        }

        public String getCallback() {
            return callback;
        }
    }
}


3.上传下载测试

	@Autowired
    private AliyunOss aliyunOss;
	/**
	 * 上传图片并下载返回预览地址
	 * @param file
	 * @return
	 * @throws IOException
	*/
	@PostMapping("/pic")
	@ApiOperation(value = "上传图片", notes = "上传图片")
	public Response<?> pic(MultipartFile file) throws IOException {
		String fileName = file.getOriginalFilename();
		boolean isOk = aliyunOss.uploadFile(fileName, AliyunOss.FileType.TEST, file.getInputStream());
		String downloadUrl = aliyunOss.getDownloadUrl(fileName, AliyunOss.FileType.TEST);
		Map<String,Object> map = new HashMap<>();
		map.put("downloadUrl",downloadUrl);
		map.put("fileName",fileName);
		return isOk ? Response.success(map) : Response.error("文件上传失败");
	}
	/**
	 * 上传视频并下载返回预览地址
	 * @param file
	 * @return
	 * @throws IOException
	*/
	@PostMapping("/video")
	@ApiOperation(value = "上传视频", notes = "上传视频")
	public Response<?> video(MultipartFile file) throws IOException {
		String fileName = file.getOriginalFilename();
		boolean isOk = aliyunOss.uploadFileVideo(fileName, AliyunOss.FileType.TEST, file.getInputStream());
		String downloadUrl = aliyunOss.getDownloadUrl(fileName, AliyunOss.FileType.TEST);
		Map<String,Object> map = new HashMap<>();
		map.put("downloadUrl",downloadUrl);
		map.put("fileName",fileName);
		return isOk ? Response.success(map) : Response.error("文件上传失败");
	}
	/**
	 * 获取上传地址
	 * @param picName
	 * @return
	 * @throws IOException
	*/
	 String videoUploadUrl = aliyunOss.getUploadUrl(picName, AliyunOss.FileType.TEST);
	/**
     * 下载文件返回字节数组
     * @param fileName 文件名称
     * @param fileType 文件路径
     * @return
    */
    public byte[] downloadFile(String fileName, FileType fileType) {
        try {
            InputStream inputStream = downloadFileInputStream(fileName, fileType);
            byte[] bytes = IOUtils.toByteArray(inputStream);
            return bytes;
        } catch (Exception e) {
            log.error("下载文件异常:{}", e.getMessage(), e);
        }
        return null;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值