封装工具类:上传/下载文件+删除文件+获取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上传一张图片
在阿里云后台我们可以看到上传成功的文件