SpringBoot+阿里云OSS

封装工具类:上传/下载文件+删除文件+获取url+获取流(可预览PDF或图片)

安装

这里选择版本为:<aliyun-oss.version>3.10.2</aliyun-oss.version>

<!-- 阿里云OSS -->
<dependency>
	<groupId>com.aliyun.oss</groupId>
	<artifactId>aliyun-sdk-oss</artifactId>
	<version>${aliyun-oss.version}</version>
 </dependency>

配置

server:
  port: 8081

aliyun:
  oss:
    # API鉴权
    accessKeyId: xxx # 访问身份验证中用到用户标识
    accessKeySecret: xxx # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
    # oss访问域名(内网)
    endpoint: oss-cn-shanghai-internal.aliyuncs.com
    bucketName: xxx-bucket # oss的存储空间
    policyExpire: 300 # url有效期(S)
    maxSize: 10 # 上传文件大小(M)

代码

配置读取

import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

/**
 * 阿里云OSS配置
 */
@Data
@Configuration
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliyunOssConfig implements InitializingBean {

    /**
     * 阿里云 oss 站点
     */
    private String endpoint;

    /**
     * 阿里云 oss 公钥
     */
    private String accessKeyId;

    /**
     * 阿里云 oss 私钥
     */
    private String accessKeySecret;

    /**
     * 阿里云 oss 文件根目录
     */
    private String bucketName;

    /**
     * url有效期(S)
     */
    private Long policyExpire;

    /**
     * 上传文件大小(M)
     */
    private Long maxSize;

    // 方便直接获取
    public static String JAVA_END_POINT;
    public static String JAVA_ACCESS_KEY_ID;
    public static String JAVA_ACCESS_KEY_SECRET;
    public static String JAVA_BUCKET_NAME;
    public static Long JAVA_POLICY_EXPIRE;
    public static Long JAVA_MAX_SIZE;

    @Override
    public void afterPropertiesSet() {
        JAVA_END_POINT = endpoint;
        JAVA_ACCESS_KEY_ID = accessKeyId;
        JAVA_ACCESS_KEY_SECRET = accessKeySecret;
        JAVA_BUCKET_NAME = bucketName;
        JAVA_POLICY_EXPIRE = policyExpire;
        JAVA_MAX_SIZE = maxSize;
    }

}

定义阿里云上传结果响应参数

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * 阿里云OSS上传结果集
 *
 * @author jason
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AliyunOssResult {

    /**
     * 上传是否成功
     */
    private boolean success;

    /**
     * 上传的文件名(如果使用自定义文件路径,会返回完整的路径+文件名,例:cf/abc.png)
     */
    private String fileName;

    /**
     * 上传成功的返回url(带过期时间)
     */
    private String url;

    /**
     * 提示信息
     */
    private String msg;

}

工具类

import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.ClientConfiguration;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.*;
import com.example.aliyunossdemo.oss.AliyunOssConfig;
import com.example.aliyunossdemo.oss.AliyunOssResult;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 阿里云OSS工具类
 *
 * @author jason
 */
public class AliyunOSSUtil {

	/**
	 * oss 工具客户端
	 */
	private static volatile OSSClient ossClient = null;

	/**
	 * 单例模式
	 * 初始化 oss 客户端
	 */
	private static OSSClient initOSS() {
		if (ossClient == null) {
			synchronized (AliyunOSSUtil.class) {
				if (ossClient == null) {
					ossClient = new OSSClient(AliyunOssConfig.JAVA_END_POINT,
							new DefaultCredentialProvider(AliyunOssConfig.JAVA_ACCESS_KEY_ID, AliyunOssConfig.JAVA_ACCESS_KEY_SECRET),
							new ClientConfiguration());
				}
			}
		}
		return ossClient;
	}

	/**
	 * 上传文件-自定义路径
	 *
	 * @param file     上传文件
	 * @param fileName 上传至OSS的文件完整路径,例:cf/abc.png
	 *                 上传至根目录,例:abc.png
	 * @return
	 */
	public static AliyunOssResult uploadFile(File file, String fileName) {
		// 文件流
		InputStream inputStream = FileUtil.getInputStream(file);
		// 获取文件类型
		String fileType = FileUtil.getType(file);

		// 上传文件
		return uploadInputStream(inputStream, fileType, fileName);
	}

	/**
	 * 上传文件-自定义路径
	 *
	 * @param file     上传文件
	 * @param fileName 上传至OSS的文件完整路径,例:cf/abc.png
	 *                 上传至根目录,例:abc.png
	 * @return
	 */
	public static AliyunOssResult uploadFile(MultipartFile file, String fileName) {
		// 文件流
		InputStream inputStream;
		try {
			inputStream = file.getInputStream();
		} catch (IOException e) {
			e.printStackTrace();
			return new AliyunOssResult(false, null, null, e.getMessage());
		}
		// 获取文件类型
		String fileType = file.getContentType();

		// 上传文件
		return uploadInputStream(inputStream, fileType, fileName);
	}

	/**
	 * 上传文件-自定义路径
	 *
	 * @param inputStream 上传文件流
	 * @param fileType    文件类型,例:png
	 * @param fileName    上传至OSS的文件完整路径,例:cf/abc.png
	 *                    上传至根目录,例:abc.png
	 * @return
	 */
	public static AliyunOssResult uploadInputStream(InputStream inputStream, String fileType, String fileName) {
		if (inputStream == null) {
			return new AliyunOssResult(false, null, null, "文件不能为空");
		}
		if (StrUtil.isBlank(fileName)) {
			return new AliyunOssResult(false, null, null, "文件名不能为空");
		}
		// 上传文件最大值 MB->bytes
		long maxSize = AliyunOssConfig.JAVA_MAX_SIZE * 1024 * 1024;
		// 本次上传文件的大小
		long fileSize = getInputStreamSize(inputStream);
		if (fileSize <= 0 || fileSize > maxSize) {
			return new AliyunOssResult(false, null, null, "请检查文件大小");
		}

		// 上传文件
		return putFile(inputStream, fileType, fileName);
	}

	/**
	 * 上传文件
	 *
	 * @param input
	 * @param fileType
	 * @param fileName
	 * @return
	 */
	private static AliyunOssResult putFile(InputStream input, String fileType, String fileName) {
		ossClient = initOSS();
		try {
			// 创建上传Object的Metadata
			ObjectMetadata meta = new ObjectMetadata();
			// 设置上传内容类型
			meta.setContentType(fileType);
			//被下载时网页的缓存行为
			meta.setCacheControl("no-cache");
			//创建上传请求
			PutObjectRequest request = new PutObjectRequest(AliyunOssConfig.JAVA_BUCKET_NAME, fileName, input, meta);
			//上传文件
			ossClient.putObject(request);

			//获取上传成功的文件地址
			return new AliyunOssResult(true, fileName, getOssUrl(fileName), "上传成功");
		} catch (OSSException | ClientException e) {
			e.printStackTrace();
			return new AliyunOssResult(false, fileName, null, e.getMessage());
		}
	}

	/**
	 * 根据文件名生成文件的访问地址(带过期时间)
	 *
	 * @param fileName
	 * @return
	 */
	public static String getOssUrl(String fileName) {
		ossClient = initOSS();
		// 生成过期时间
		long expireEndTime = System.currentTimeMillis() + AliyunOssConfig.JAVA_POLICY_EXPIRE * 1000;
		Date expiration = new Date(expireEndTime);// 生成URL
		GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(AliyunOssConfig.JAVA_BUCKET_NAME, fileName);
		generatePresignedUrlRequest.setExpiration(expiration);
		URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
		return url.toString();
	}

	/**
	 * 通过文件名下载文件
	 *
	 * @param fileName      要下载的文件名(OSS服务器上的)
	 *                      例如:4DB049D0604047989183CB68D76E969D.jpg
	 * @param localFileName 本地要创建的文件名(下载到本地的)
	 *                      例如:C:\Users\Administrator\Desktop\test.jpg
	 */
	public static void downloadFile(String fileName, String localFileName) {
		ossClient = initOSS();
		// 下载OSS文件到指定目录。如果指定的本地文件存在会覆盖,不存在则新建。
		ossClient.getObject(new GetObjectRequest(AliyunOssConfig.JAVA_BUCKET_NAME, fileName), new File(localFileName));
	}

	/**
	 * 通过文件名获取文件流
	 *
	 * @param fileName 要下载的文件名(OSS服务器上的)
	 *                 例如:4DB049D0604047989183CB68D76E969D.jpg
	 */
	public static InputStream getInputStream(String fileName) {
		ossClient = initOSS();
		// 下载OSS文件到本地文件。如果指定的本地文件存在会覆盖,不存在则新建。
		return ossClient.getObject(new GetObjectRequest(AliyunOssConfig.JAVA_BUCKET_NAME, fileName)).getObjectContent();
	}

	/**
	 * 通过文件名获取byte[]
	 *
	 * @param fileName 要下载的文件名(OSS服务器上的)
	 *                 例如:4DB049D0604047989183CB68D76E969D.jpg
	 */
	public static byte[] getBytes(String fileName) {
		InputStream inputStream = getInputStream(fileName);
		FastByteArrayOutputStream fastByteArrayOutputStream = IoUtil.read(inputStream);
		return fastByteArrayOutputStream.toByteArray();
	}

	/**
	 * 根据文件名删除文件
	 *
	 * @param fileName 需要删除的文件名
	 * @return boolean 是否删除成功
	 * 例如:4DB049D0604047989183CB68D76E969D.jpg
	 */
	public static boolean deleteFile(String fileName) {
		ossClient = initOSS();
		try {
			if (AliyunOssConfig.JAVA_BUCKET_NAME == null || fileName == null) return false;
			GenericRequest request = new DeleteObjectsRequest(AliyunOssConfig.JAVA_BUCKET_NAME).withKey(fileName);
			ossClient.deleteObject(request);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 列举所有的文件url
	 */
	public static List<String> urlList() {
		ossClient = initOSS();
		List<String> list = new ArrayList<>();
		// 构造ListObjectsRequest请求
		ListObjectsRequest listObjectsRequest = new ListObjectsRequest(AliyunOssConfig.JAVA_BUCKET_NAME);
		// 列出文件
		ObjectListing listing = ossClient.listObjects(listObjectsRequest);
		// 遍历所有文件
		for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
			// 把key全部转化成可以访问的url
			String url = getOssUrl(objectSummary.getKey());
			list.add(url);
		}
		return list;
	}

	/**
	 * 现象:inputStream.available() == 0 但实际文件不为空
	 * 原因:从网络中读取InputStream后,可能因网络质量一次读取后InputStream长度为0,这里最多读5次,没读到就视为0
	 */
	private static long getInputStreamSize(InputStream inputStream) {
		long fileSize = 0;
		int cunt = 1;
		try {
			while (fileSize == 0 && cunt <= 5) {
				fileSize = inputStream.available();
				cunt++;
			}
		} catch (IOException ignored) {
		}
		return fileSize;
	}

}

测试

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import com.example.aliyunossdemo.oss.AliyunOssResult;
import com.example.aliyunossdemo.util.AliyunOSSUtil;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.util.List;

/**
 * 阿里云OSS测试接口
 *
 * @author jason
 */
@RestController
@RequestMapping("/oss")
public class OssTestController {

	/**
	 * 测试-上传
	 * -自定义文件
	 * -自定义OSS存储路径
	 * http://localhost:8081/oss/uploadFile
	 */
	@GetMapping("/uploadFile")
	public AliyunOssResult uploadFile() {
		return AliyunOSSUtil.uploadFile(new File("src/main/resources/xxx.png"), "png/重命名.png");
	}

	/**
	 * 上传文件-指定目录
	 */
	@PostMapping("/uploadTest")
	public AliyunOssResult uploadTest(MultipartFile file) {
		return AliyunOSSUtil.uploadFile(file, "自定义目录/" + file.getOriginalFilename());
	}

	/**
	 * 删除文件
	 * http://localhost:8081/oss/deleteFile?fileName=TEST/png/重命名.png
	 */
	@GetMapping("/deleteFile")
	public boolean deleteFile(@RequestParam String fileName) {
		return AliyunOSSUtil.deleteFile(fileName);
	}

	/**
	 * oss路径下获取文件带有效期的url,获取的url可下载
	 * http://localhost:8081/oss/getOssUrl?fileName=TEST/png/重命名.png
	 */
	@GetMapping("/getOssUrl")
	public String getOssUrl(@RequestParam String fileName) {
		return AliyunOSSUtil.getOssUrl(fileName);
	}

	/**
	 * 预览PDF或图片
	 * http://localhost:8081/oss/preview?fileName=TEST/png/重命名.png
	 */
	@GetMapping("/preview")
	public ResponseEntity<InputStreamResource> previewFile(@RequestParam String fileName) {
		// 获取文件类型
		String contentType = FileUtil.extName(fileName);
		// 获取文件流
		InputStream inputStream = AliyunOSSUtil.getInputStream(fileName);
		// 预览
		HttpHeaders httpHeaders = new HttpHeaders();
		if ("pdf".equalsIgnoreCase(contentType)) {
			httpHeaders.add("Content-Type", MediaType.APPLICATION_PDF_VALUE);
		} else if ("jpg".equalsIgnoreCase(contentType) || "png".equalsIgnoreCase(contentType) || "jpeg".equalsIgnoreCase(contentType)) {
			httpHeaders.add("Content-Type", MediaType.IMAGE_JPEG_VALUE);
		}
		InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
		return new ResponseEntity<>(inputStreamResource, httpHeaders, HttpStatus.OK);
	}

	/**
	 * 列举所有的文件url
	 * http://localhost:8081/oss/urlList
	 */
	@GetMapping("/urlList")
	public List<String> urlList() {
		return AliyunOSSUtil.urlList();
	}

	/**
	 * 图片转base64
	 * http://localhost:8081/oss/base64
	 */
	@GetMapping("/base64")
	public String base64() {
		return Base64.encode(AliyunOSSUtil.getInputStream("png/重命名.png"));
	}

	/**
	 * 文件转byte[]
	 * http://localhost:8081/oss/bytes
	 */
	@GetMapping("/bytes")
	public byte[] bytes() {
		return AliyunOSSUtil.getBytes("png/重命名.png");
	}

}

效果

使用postman上传一张图片
在这里插入图片描述
在阿里云后台我们可以看到上传成功的文件
在这里插入图片描述

源码

点击下载

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值