一、需求
使用阿里云oss对图片进行等质量压缩,转换成webp格式的压缩图。
二、引入依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.9.1</version>
</dependency>
三、配置文件
yaml
spring:
application:
name: infra-server
# Servlet 配置
servlet:
# 文件上传相关配置项
multipart:
max-file-size: 200MB # 单个文件大小
max-request-size: 200MB # 设置总上传的文件大小
server:
port: 8081
# 阿里云OSS配置
aliyun:
oss:
endpoint: oss-cn-beijing.aliyuncs.com # 例如:oss-cn-hangzhou.aliyuncs.com
accessKeyId: KJSDH5tRKWIJHSBhc8WKKB17PO
accessKeySecret: ri7KJSDH5tRKISJH87hc8WKKB17POxD
bucketName: oss-prod
cyjBucketName: oss-bigdata-cyj-prod
directory: dir
apkBucketName: oss-prod-apk
apkEndpoint: prod.oss.com
domain: https://oss-prod.oss-cn-beijing.aliyuncs.com # OSS访问域名
original-image: original_image/ # 原始图片
thumbnail-image: thumbnail_image/ # 缩略图
webp-quality: 90 #质量分
四、文件相关实体类
1、系统文件关联实体类
java
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 系统文件关联实体类
*/
@Data
public class SysFileRelationVo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 文件关联ID
*/
private String id;
/**
* 文件名称
*/
private String fileName;
/**
* 文件ID
*/
private String fileId;
/**
* 文件路径
*/
private String filePath;
/**
*关联文件ID
*/
private String relatedFileId;
/**
*关联类型
*/
private String relationType;
/**
* 文件大小(字节)
*/
private Long fileSize;
/**
*关联名称
*/
private String relationName;
/**
*关联描述
*/
private String description;
/**
* 文件类型
*/
private String fileType;
/**
* 文件类型
*/
private String mimeType;
/**
* OSS文件ID
*/
private String ossFileId;
/**
* 业务类型
*/
private String businessType;
/**
* 业务ID
*/
private String businessId;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 创建人
*/
private String createBy;
/**
* 更新人
*/
private String updateBy;
/**
* 文件路径
*/
private String ossPath;
/**
* 状态:0-禁用,1-启用
*/
private Integer status;
private String avatarUrl;
}
2、批量获取文件实体类
java
import lombok.Data;
@Data
public class FileBatchUrlsVO {
private String id;
private String url;
}
3、上传文件并压缩实体类
java
import lombok.Data;
@Data
public class OssFileRespVO {
private String originalUrl;
private String originalPath;
private String thumbnailUrl;
private String thumbnailPath;
private String originalFilename;
private String thumbnailFilename;
}
五、工具类
java
import com.alibaba.fastjson.JSON;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.model.*;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* OSS工具类
*/
@Slf4j
@Data
@Component
@RefreshScope
public class OssUtil {
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
@Value("${aliyun.oss.cyjBucketName}")
private String cyjBucketName;
@Value("${aliyun.oss.directory}")
private String directory;
@Value("${aliyun.oss.apkBucketName}")
private String apkBucketName;
@Value("${aliyun.oss.apkEndpoint}")
private String apkEndpoint;
@Value("${aliyun.oss.original-image}")
private String originalImage;
@Value("${aliyun.oss.thumbnail-image}")
private String thumbnailImage;
@Value("${aliyun.oss.domain}")
private String domain;
@Value("${aliyun.oss.webp-quality:92}")
private int webpQuality;
private static final int THREAD_POOL_SIZE = 10; // 线程池大小
private static final long URL_EXPIRE_TIME = 3600 * 1000; // 签名URL有效期(毫秒)
/**
* 上传文件
*
* @param file 文件
* @param dir 目录
* @return OSS路径
*/
public String upload(MultipartFile file, String dir) {
String originalFilename = file.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
String objectName = dir + "/" + fileName;
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
InputStream inputStream = file.getInputStream();
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
metadata.setContentLength(file.getSize());
ossClient.putObject(bucketName, objectName, inputStream, metadata);
return objectName;
} catch (IOException e) {
log.error("上传文件失败", e);
throw new RuntimeException("上传文件失败");
} finally {
ossClient.shutdown();
}
}
public String uploadByBase64(byte[] bytes, String bucketName, String dir, String originalFilename) {
String suffix = ".png";
String fileName = StringUtils.isBlank(originalFilename) ? UUID.randomUUID().toString().replace("-", "") + suffix : originalFilename + suffix;
String objectName = dir + "/" + fileName;
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 转换为InputStream
InputStream inputStream = new ByteArrayInputStream(bytes);
ObjectMetadata metadata = new ObjectMetadata();
// 这里假设所有文件都有标准的Content-Type,如果需要更精确控制可以增加参数
metadata.setContentType("application/octet-stream");
metadata.setContentLength(bytes.length);
ossClient.putObject(bucketName, objectName, inputStream, metadata);
return objectName;
} catch (Exception e) {
log.error("上传文件失败", e);
throw new RuntimeException("上传文件失败");
} finally {
ossClient.shutdown();
}
}
public String uploadByBase64(byte[] bytes, String dir) {
return uploadByBase64(bytes, bucketName, dir, null);
}
/**
* 获取文件URL
*
* @param objectName 对象名称
* @param expiration 过期时间(秒)
* @return 文件URL
*/
public String getFileUrl(String objectName, long expiration) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
Date expireDate = new Date(System.currentTimeMillis() + expiration * 1000);
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName);
request.setExpiration(expireDate);
URL url = ossClient.generatePresignedUrl(request);
return url.toString();
} finally {
ossClient.shutdown();
}
}
/**
* 删除文件
*
* @param objectName 对象名称
*/
public void deleteFile(String objectName) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
ossClient.deleteObject(bucketName, objectName);
} finally {
ossClient.shutdown();
}
}
/**
* 从OSS下载文件到本地
*
* @param objectName OSS对象名称
* @param localFilePath 本地文件保存路径
* @return 是否下载成功
*/
/* public boolean downloadFile(String objectName, String localFilePath) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
ossClient.getObject(bucketName, objectName, new java.io.File(localFilePath));
return true;
} catch (Exception e) {
log.error("从OSS下载文件失败: {}", e.getMessage(), e);
return false;
} finally {
ossClient.shutdown();
}
}*/
/**
* 获取OSS文件的输入流
*
* @param objectName OSS对象名称
* @return 文件输入流,如果获取失败则返回null
*/
public InputStream getFileInputStream(String objectName) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
return ossClient.getObject(bucketName, objectName).getObjectContent();
} catch (Exception e) {
log.error("获取OSS文件输入流失败: {}", e.getMessage(), e);
return null;
}
// 注意:这里不关闭ossClient,因为关闭后输入流也会被关闭
// 调用方需要负责在使用完输入流后关闭它,并调用ossClient.shutdown()
}
/**
* 获取OSS文件的字节数组
*
* @param objectName OSS对象名称
* @return 文件字节数组,如果获取失败则返回null
*/
public byte[] getFileBytes(String objectName) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
InputStream inputStream = null;
try {
inputStream = ossClient.getObject(bucketName, objectName).getObjectContent();
return inputStream.readAllBytes();
} catch (Exception e) {
log.error("获取OSS文件字节数组失败: {}", e.getMessage(), e);
return null;
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
log.error("关闭输入流失败", e);
}
ossClient.shutdown();
}
}
/**
* 将OSS文件转换为MultipartFile对象
*
* @param objectName OSS对象名称
* @return MultipartFile对象,如果获取失败则返回null
*/
public MultipartFile getOssFileAsMultipartFile(String objectName) {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 获取文件元数据
ObjectMetadata metadata = ossClient.getObjectMetadata(bucketName, objectName);
// 获取文件内容
byte[] content = getFileBytes(objectName);
if (content == null) {
return null;
}
// 获取文件名(从objectName中提取)
String fileName = objectName;
if (objectName.contains("/")) {
fileName = objectName.substring(objectName.lastIndexOf("/") + 1);
}
// 创建自定义的MultipartFile实现
String finalFileName = fileName;
return new MultipartFile() {
@Override
public String getName() {
return "file";
}
@Override
public String getOriginalFilename() {
return finalFileName;
}
@Override
public String getContentType() {
return metadata.getContentType();
}
@Override
public boolean isEmpty() {
return content.length == 0;
}
@Override
public long getSize() {
return content.length;
}
@Override
public byte[] getBytes() throws IOException {
return content;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(content);
}
@Override
public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
try (java.io.FileOutputStream fos = new java.io.FileOutputStream(dest)) {
fos.write(content);
}
}
};
} catch (Exception e) {
log.error("将OSS文件转换为MultipartFile失败: {}", e.getMessage(), e);
return null;
} finally {
ossClient.shutdown();
}
}
/**
* 将文字内容上传到 OSS
*
* @param text 要上传的文字内容
*/
public String uploadTextToOSS(String text, String dir, String fileName) {
// 创建 OSSClient 实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
String objectName = dir + "/" + fileName;
try {
// 将文字内容转换为字节数组输入流
ByteArrayInputStream inputStream = new ByteArrayInputStream(text.getBytes());
// 创建 PutObjectRequest 对象
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 上传文件
ossClient.putObject(putObjectRequest);
System.out.println("文字内容已成功上传到 OSS。");
return objectName;
} catch (Exception e) {
throw new RuntimeException("上传过程中出现错误: " + e.getMessage());
} finally {
// 关闭 OSSClient
ossClient.shutdown();
}
}
/**
* 将文字内容以 Word 文件形式上传到 OSS
*
* @param text 要上传的文字内容
* @throws IOException 可能的 IO 异常
*/
public String uploadTextAsWordToOSS(String text, String dir, String fileName) {
// 创建 OSSClient 实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 创建 Word 文档
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText(text);
// 将文档内容写入字节数组输出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
document.write(outputStream);
byte[] wordBytes = outputStream.toByteArray();
String objectName = dir + "/" + fileName;
// 将字节数组转换为字节数组输入流
ByteArrayInputStream inputStream = new ByteArrayInputStream(wordBytes);
// 创建 PutObjectRequest 对象
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 上传文件
ossClient.putObject(putObjectRequest);
System.out.println("文字内容已成功以 Word 文件形式上传到 OSS。");
return objectName;
} catch (Exception e) {
throw new RuntimeException("上传过程中出现错误: " + e.getMessage());
} finally {
// 关闭 OSSClient
ossClient.shutdown();
}
}
public String uploadRichTextToOSS(String richText, String dir, String fileName) throws IOException, InvalidFormatException {
// 创建 Word 文档
XWPFDocument document = new XWPFDocument();
// 解析富文本
Document htmlDoc = Jsoup.parse(richText);
Elements elements = htmlDoc.body().children();
for (Element element : elements) {
if (element.tagName().equals("p")) {
// 处理段落文本
String text = element.text();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText(text);
} else if (element.tagName().equals("img")) {
// 处理图片
String imgUrl = element.attr("src");
addImageToDocument(document, imgUrl);
}
}
// 将文档内容写入字节数组输出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
document.write(outputStream);
byte[] wordBytes = outputStream.toByteArray();
// 创建 OSSClient 实例
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
String objectName = dir + "/" + fileName;
try {
// 将字节数组转换为字节数组输入流
ByteArrayInputStream inputStream = new ByteArrayInputStream(wordBytes);
// 创建 PutObjectRequest 对象
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
// 上传文件
ossClient.putObject(putObjectRequest);
return objectName;
} catch (Exception e) {
throw new RuntimeException("上传过程中出现错误: " + e.getMessage());
} finally {
// 关闭 OSSClient
ossClient.shutdown();
}
}
private static void addImageToDocument(XWPFDocument document, String imgUrl) throws IOException, InvalidFormatException {
URL url = new URL(imgUrl);
InputStream inputStream = url.openStream();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
byte[] imageBytes = outputStream.toByteArray();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
int format = getImageFormat(imgUrl);
run.addPicture(new ByteArrayInputStream(imageBytes), format, "image", Units.toEMU(200), Units.toEMU(200));
}
private static int getImageFormat(String imgUrl) {
if (imgUrl.endsWith(".png")) {
// return Document.PICTURE_TYPE_PNG;
return 1;
} else if (imgUrl.endsWith(".jpg") || imgUrl.endsWith(".jpeg")) {
// return Document.PICTURE_TYPE_JPEG;
return 2;
}
// return Document.PICTURE_TYPE_PNG;
return 1;
}
/**
* 多线程并发生成URL
*/
public Map<String, String> generateUrlsMultiThread(List<String> fileIds) {
Map<String, String> urlMap = new ConcurrentHashMap<>();
ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
List<Future<Map<String, String>>> futures = new ArrayList<>();
// 分割任务
int batchSize = 100;
for (int i = 0; i < fileIds.size(); i += batchSize) {
List<String> batch = fileIds.subList(i, Math.min(i + batchSize, fileIds.size()));
futures.add(executor.submit(() -> {
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
Map<String, String> batchUrls = new HashMap<>();
try {
for (String fileId : batch) {
batchUrls.put(fileId, generateSignedUrl(ossClient, fileId));
}
} finally {
ossClient.shutdown();
}
return batchUrls;
}));
}
// 收集结果
for (Future<Map<String, String>> future : futures) {
try {
urlMap.putAll(future.get());
} catch (Exception e) {
e.printStackTrace();
}
}
executor.shutdown();
return urlMap;
}
public List<FileBatchUrlsVO> getUrlsList(List<String> fileIds) {
if (CollectionUtils.isEmpty(fileIds)) {
return Collections.emptyList();
}
Map<String, String> stringStringMap = generateUrlsMultiThread(fileIds);
if (null == stringStringMap || stringStringMap.isEmpty()) {
return Collections.emptyList();
}
List<FileBatchUrlsVO> fileBatchUrlsVOS = new ArrayList<>();
for (Map.Entry<String, String> entry : stringStringMap.entrySet()) {
FileBatchUrlsVO vo = new FileBatchUrlsVO();
vo.setId(entry.getKey());
vo.setUrl(entry.getValue());
fileBatchUrlsVOS.add(vo);
}
return fileBatchUrlsVOS;
}
/**
* 生成单个签名URL
*/
public String generateSignedUrl(OSS ossClient, String fileId) {
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, fileId);
request.setExpiration(new Date(System.currentTimeMillis() + URL_EXPIRE_TIME));
URL url = ossClient.generatePresignedUrl(request);
return url.toString();
}
/**
* 获取公共读文件的访问URL
*/
public String getPublicUrl(String ossFilePath) {
return String.format("https://%s.%s/%s", bucketName, endpoint, ossFilePath);
}
/**
* 批量获取公共读文件的访问URL
*/
public List<FileBatchUrlsVO> getPublicUrlsList(List<String> fileIds) {
if (CollectionUtils.isEmpty(fileIds)) {
return Collections.emptyList();
}
List<FileBatchUrlsVO> fileBatchUrlsVOS = new ArrayList<>();
for (String fileId : fileIds) {
if (StringUtils.isBlank(fileId)) {
continue;
}
String publicUrl = getPublicUrl(fileId);
FileBatchUrlsVO vo = new FileBatchUrlsVO();
vo.setId(fileId);
vo.setUrl(publicUrl);
fileBatchUrlsVOS.add(vo);
}
return fileBatchUrlsVOS;
}
/**
* 从cyjBucketName桶的指定目录下获取任意一个PNG图片的访问地址
*
* @return PNG图片的访问URL地址,如果没有找到则返回null
*/
public String getRandomPngFromCyjBucket() {
String directoryPath = "photos/product/630内容数据_已全部移到此目录下/专属衣橱模块/海报大片图/";
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try {
// 列出目录下的所有文件
ListObjectsRequest listObjectsRequest = new ListObjectsRequest(cyjBucketName);
listObjectsRequest.setPrefix(directoryPath);
ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);
List<OSSObjectSummary> objectSummaries = objectListing.getObjectSummaries();
// 过滤出PNG文件
List<String> pngFiles = new ArrayList<>();
for (OSSObjectSummary objectSummary : objectSummaries) {
String key = objectSummary.getKey();
if (key.toLowerCase().endsWith(".png")) {
pngFiles.add(key);
}
}
// 如果找到PNG文件,生成第一个文件的永久访问URL
if (!pngFiles.isEmpty()) {
String selectedPngFile = pngFiles.get(0);
log.info("在目录 {} 下找到 {} 个PNG文件,返回第一个: {}", directoryPath, pngFiles.size(), selectedPngFile);
// 生成永久访问URL
String permanentUrl = String.format("https://%s.%s/%s", cyjBucketName, endpoint, selectedPngFile);
return permanentUrl;
}
log.warn("在目录 {} 下未找到PNG文件", directoryPath);
return null;
} catch (Exception e) {
log.error("获取PNG文件失败: {}", e.getMessage(), e);
return null;
} finally {
ossClient.shutdown();
}
}
/**
* 上传文件
*
* @param file 文件
* @param dir 目录
* @return OSS路径
*/
public String uploadApk(MultipartFile file, String dir) {
String originalFilename = file.getOriginalFilename();
String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
String fileName = UUID.randomUUID().toString().replace("-", "") + suffix;
String objectName = dir + "/" + fileName;
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
// 开启CNAME选项以支持自定义域名访问
clientBuilderConfiguration.setSupportCname(true);
OSS ossClient = new OSSClientBuilder().build("https://" + apkEndpoint, accessKeyId, accessKeySecret, clientBuilderConfiguration);
try {
InputStream inputStream = file.getInputStream();
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
metadata.setContentLength(file.getSize());
log.info("上传文件的桶是: {}", apkBucketName);
ossClient.putObject(apkBucketName, objectName, inputStream, metadata);
return objectName;
} catch (IOException e) {
log.error("apk上传文件失败", e);
throw new RuntimeException("上传文件失败");
} finally {
ossClient.shutdown();
}
}
/**
* 获取公共读文件的访问URL
*/
public String getPublicUrlApk(String ossFilePath) {
return String.format("https://%s/%s", apkEndpoint, ossFilePath);
}
/**
* 将图片压缩并上传--保留了原始图片和压缩图片
*
* @param file 文件
* @return OSS路径
*/
public OssFileRespVO uploadImageZip(MultipartFile file) {
// 1. 校验文件类型(同上)
String originalFilename = file.getOriginalFilename();
log.info("将图片压缩并上传开始 originalFilename={}", originalFilename);
if (originalFilename == null || !originalFilename.matches(".*\\.(jpg|jpeg|png|gif|bmp|webp)$")) {
throw new IllegalArgumentException("仅支持jpg、jpeg、png、gif、bmp、webp格式");
}
// 2. 生成存储路径(注意:路径中避免中文和特殊字符)
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String originalExt = getFileExt(originalFilename);
String originalOssKey = originalImage + uuid + originalExt;
String webpOssKey = thumbnailImage + uuid + ".webp";
log.info("将图片压缩并上传路径 originalOssKey={} webpOssKey={}", originalOssKey, webpOssKey);
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
log.info("将图片压缩并上传初始化ossClient完成");
// 3. 上传原始图片
try (InputStream inputStream = file.getInputStream()) {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
PutObjectResult putObjectResult = ossClient.putObject(bucketName, originalOssKey, inputStream, metadata);
log.info("将图片压缩并上传原始图片返回结果 putObjectResult={}", JSON.toJSONString(putObjectResult));
ResponseMessage response = putObjectResult.getResponse();
if (putObjectResult.getResponse().getStatusCode() != 200) {
throw new RuntimeException("OSS上传原始图片失败");
}
// 4. 构造处理规则(关键:使用OSS专用Base64编码)
// 格式:image/format,webp|sys/saveas,o_<Base64编码的目标路径>,b_<Base64编码的存储桶>
String encodedKey = OSSBase64Utils.encode(webpOssKey); // 编码目标路径
String encodedBucket = OSSBase64Utils.encode(bucketName); // 编码存储桶
int quality = Math.min(100, Math.max(1, webpQuality));
String processRule = String.format(
"image/quality,q_%d/format,webp|sys/saveas,o_%s,b_%s",
quality,
encodedKey,
encodedBucket
);
// 5. 执行处理
ProcessObjectRequest processRequest = new ProcessObjectRequest(bucketName, originalOssKey, processRule);
GenericResult result = ossClient.processObject(processRequest);
log.info("将图片压缩并上传压缩图片返回结果 result={}", JSON.toJSONString(result));
// 6. 验证处理成功
if (result.getResponse().getStatusCode() != 200) {
throw new RuntimeException("OSS生成WebP失败,状态码:" + result.getResponse().getStatusCode());
}
// 7. 返回WebP访问URL
OssFileRespVO ossFileRespVO = new OssFileRespVO();
ossFileRespVO.setOriginalUrl(domain + "/" + originalOssKey);
ossFileRespVO.setThumbnailUrl(domain + "/" + webpOssKey);
ossFileRespVO.setOriginalPath(originalOssKey);
ossFileRespVO.setThumbnailPath(webpOssKey);
log.info("将图片压缩并上传压返回结果 ossFileRespVO={}", JSON.toJSONString(ossFileRespVO));
return ossFileRespVO;
} catch (Exception e) {
log.error("将图片压缩并上传失败", e);
throw new RuntimeException("上传文件失败");
} finally {
ossClient.shutdown();
}
}
private String getFileExt(String filename) {
return filename.substring(filename.lastIndexOf("."));
}
}
六、文件服务service接口
java
import cn.iocoder.yudao.module.infra.controller.admin.vo.FileBatchUrlsVO;
import cn.iocoder.yudao.module.infra.controller.admin.vo.FileUploadReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.vo.OssFileRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.vo.SysFileRelationVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 文件 Service 接口
*
* @author 芋道源码
*/
public interface OssFileService {
/**
* 上传文件--返回临时URL
*
* @param uploadReqVO
* @return
*/
SysFileRelationVo upload(FileUploadReqVO uploadReqVO);
/**
* 上传文件--返回永久URL
*
* @param uploadReqVO
* @return
*/
String uploadStr(FileUploadReqVO uploadReqVO);
/**
* 获取文件URL--临时
*
* @param fileName
* @return
*/
String getUrl(String fileName);
/**
* 批量获取文件URL--临时
*
* @param fileNames
* @return
*/
List<FileBatchUrlsVO> getUrls(List<String> fileNames);
/**
* 批量获取文件URL--永久
*
* @param fileNames
* @return
*/
List<FileBatchUrlsVO> getPermanentUrl(List<String> fileNames);
/**
* 上传文件--返回永久URL
*
* @param base64Str
* @return
*/
String uploadByBase64(String base64Str,String fileType);
/**
* 上传文件--返回永久URL
*
* @param base64Data base64 数据
* @param bucketName 桶名称
* @param dir 目录
* @param fileType 文件类型
* @return
*/
String uploadByBase64(String base64Data,String bucketName, String dir,String fileName,String fileType);
/**
* 上传文件--返回永久URL
*
* @param uploadReqVO
* @return
*/
String uploadStrApk(FileUploadReqVO uploadReqVO);
/**
* 上传文件并压缩--返回永久URL
*
* @param uploadReqVO
* @return
*/
OssFileRespVO uploadZip(FileUploadReqVO uploadReqVO);
/**
* 上传文件并压缩--返回永久URL
*
* @param file
* @return
*/
String uploadZipFile(MultipartFile file);
/**
* 压缩图片并上传--调用oss--base64Data入参
*
* @param base64Data
* @return
*/
String uploadZipBase64Method(String base64Data, String fileType);
/**
* 压缩图片并上传--调用oss--base64Data入参
*
* @param base64Data
* @return 返回png图片
*/
String uploadZipBase64(String base64Data, String fileType);
}
七、文件服务service接口实现类
java
import cn.hutool.core.io.IoUtil;
import cn.iocoder.yudao.framework.common.enums.ImageTypeEnum;
import cn.iocoder.yudao.module.infra.controller.admin.vo.FileBatchUrlsVO;
import cn.iocoder.yudao.module.infra.controller.admin.vo.FileUploadReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.vo.OssFileRespVO;
import cn.iocoder.yudao.module.infra.controller.admin.vo.SysFileRelationVo;
import cn.iocoder.yudao.module.infra.framework.file.core.utils.FileTypeUtils;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.module.infra.orm.entity.FileDO;
import cn.iocoder.yudao.module.infra.orm.mapper.FileMapper;
import cn.iocoder.yudao.module.infra.service.config.ConfigDataService;
import cn.iocoder.yudao.module.infra.utils.OSSBase64Utils;
import cn.iocoder.yudao.module.infra.utils.OssUtil;
import com.alibaba.nacos.common.utils.StringUtils;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.GenericResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.ProcessObjectRequest;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.List;
import java.util.UUID;
/**
* 文件 Service 实现类
*
* @author 芋道源码
*/
@Slf4j
@Service
@RefreshScope
public class OssFileServiceImpl implements OssFileService {
@Resource
private FileConfigService fileConfigService;
@Resource
private OssUtil ossUtil;
@Resource
private ConfigDataService configDataService;
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;
@Value("${aliyun.oss.original-image}")
private String originalImage;
@Value("${aliyun.oss.thumbnail-image}")
private String thumbnailImage;
@Value("${aliyun.oss.domain}")
private String domain;
/**
* OSS 转 WebP 的相对质量(1-100),默认 92。未配置 quality 时 OSS 会使用较低默认值导致画质偏糊。
*/
@Value("${aliyun.oss.webp-quality:92}")
private int webpQuality;
@Override
@SneakyThrows
public SysFileRelationVo upload(FileUploadReqVO uploadReqVO) {
try {
String originalFilename = uploadReqVO.getFile().getOriginalFilename();
// 上传到OSS
String ossPath = ossUtil.upload(uploadReqVO.getFile(), configDataService.getDirectory());
String fileUrl = ossUtil.getFileUrl(ossPath, 24 * 60 * 60);
MultipartFile file1 = uploadReqVO.getFile();
String path = uploadReqVO.getPath();
byte[] bytes = IoUtil.readBytes(file1.getInputStream());
String type = FileTypeUtils.getMineType(bytes, originalFilename);
SysFileRelationVo vo = new SysFileRelationVo();
vo.setOssFileId(ossPath);
vo.setAvatarUrl(fileUrl);
return vo;
} catch (Exception e) {
log.error("上传文件失败", e);
throw new RuntimeException("上传头像失败");
}
}
@Override
public String uploadByBase64(String base64Data, String bucketName, String dir, String fileName, String fileType) {
try {
if (base64Data.startsWith("data:")) {
base64Data = base64Data.substring(base64Data.indexOf(",") + 1);
}
// 解码Base64
byte[] decodedBytes = Base64.getDecoder().decode(base64Data);
// 上传到OSS
String ossPath = ossUtil.uploadByBase64(decodedBytes, bucketName, dir, fileName);
String fileUrl = ossUtil.getPublicUrl(ossPath);
String originalFilename = StringUtils.isBlank(fileName) ? UUID.randomUUID().toString().replace("-", "") + ".png" : fileName + ".png";
String type = FileTypeUtils.getMineType(decodedBytes, originalFilename);
return fileUrl;
} catch (Exception e) {
log.error("上传文件失败", e);
throw new RuntimeException("上传头像失败");
}
}
@Override
public String uploadByBase64(String base64Data, String fileType) {
return uploadByBase64(base64Data, configDataService.getBucketName(), configDataService.getDirectory(), null, fileType);
}
@Override
public String uploadStr(FileUploadReqVO uploadReqVO) {
String fileType = uploadReqVO.getType();
ImageTypeEnum imageTypeEnum = ImageTypeEnum.valueOfCode(fileType);
log.info("uploadStr上传文件,文件类型:{},文件名:{}, 路径:{}",
imageTypeEnum == null ? "未知" : imageTypeEnum.getName(),
uploadReqVO.getFile().getOriginalFilename(), uploadReqVO.getPath());
try {
String originalFilename = uploadReqVO.getFile().getOriginalFilename();
// 上传到OSS
String ossPath = ossUtil.upload(uploadReqVO.getFile(), configDataService.getDirectory());
log.info("uploadStr上传文件ossPath:{}", ossPath);
String fileUrl = ossUtil.getPublicUrl(ossPath);
MultipartFile file1 = uploadReqVO.getFile();
byte[] bytes = IoUtil.readBytes(file1.getInputStream());
String type = FileTypeUtils.getMineType(bytes, originalFilename);
return fileUrl;
} catch (Exception e) {
log.error("上传文件失败", e);
throw new RuntimeException("上传头像失败");
}
}
@Override
public String getUrl(String fileName) {
return ossUtil.getFileUrl(fileName, 24 * 60 * 60);
}
@Override
public List<FileBatchUrlsVO> getUrls(List<String> fileNames) {
return ossUtil.getUrlsList(fileNames);
}
@Override
public List<FileBatchUrlsVO> getPermanentUrl(List<String> fileNames) {
return ossUtil.getPublicUrlsList(fileNames);
}
@Override
public String uploadStrApk(FileUploadReqVO uploadReqVO) {
String fileType = uploadReqVO.getType();
ImageTypeEnum imageTypeEnum = ImageTypeEnum.valueOfCode(fileType);
log.info("uploadStr上传文件,文件类型:{},文件名:{}, 路径:{}",
imageTypeEnum == null ? "未知" : imageTypeEnum.getName(),
uploadReqVO.getFile().getOriginalFilename(), uploadReqVO.getPath());
try {
String originalFilename = uploadReqVO.getFile().getOriginalFilename();
// 上传到OSS
String ossPath = ossUtil.uploadApk(uploadReqVO.getFile(), configDataService.getDirectory());
log.info("apk uploadStrApk上传文件ossPath:{}", ossPath);
String fileUrl = ossUtil.getPublicUrlApk(ossPath);
MultipartFile file1 = uploadReqVO.getFile();
byte[] bytes = IoUtil.readBytes(file1.getInputStream());
String type = FileTypeUtils.getMineType(bytes, originalFilename);
return fileUrl;
} catch (Exception e) {
log.error("apk上传文件失败", e);
throw new RuntimeException("上传头像失败");
}
}
@Override
public OssFileRespVO uploadZip(FileUploadReqVO uploadReqVO) {
try {
String originalFilename = uploadReqVO.getFile().getOriginalFilename();
// 上传到OSS
OssFileRespVO ossVO = uploadZipFileMethod(uploadReqVO.getFile());
// String ossVO1 = uploadZipFile(uploadReqVO.getFile());
byte[] bytes = IoUtil.readBytes(uploadReqVO.getFile().getInputStream());
String type = FileTypeUtils.getMineType(bytes, originalFilename);
OssFileRespVO vo = new OssFileRespVO();
vo.setThumbnailUrl(ossVO.getThumbnailUrl());
return vo;
} catch (Exception e) {
log.error("上传文件并压缩失败", e);
throw new RuntimeException("上传文件并压缩失败");
}
}
@Override
public String uploadZipFile(MultipartFile file) {
OssFileRespVO ossFileRespVO = uploadZipFileMethod(file);
return ossFileRespVO.getThumbnailUrl();
}
/**
* 压缩图片并上传--调用oss--入参MultipartFile
*
* @param file
* @return
*/
public OssFileRespVO uploadZipFileMethod(MultipartFile file) {
// 1. 校验文件类型(同上)
String originalFilename = file.getOriginalFilename();
if (originalFilename == null || !originalFilename.toLowerCase().matches(".*\\.(jpg|jpeg|png|gif|bmp|webp)$")) {
throw new IllegalArgumentException("仅支持jpg、jpeg、png、gif、bmp、webp格式");
}
// 2. 生成存储路径(注意:路径中避免中文和特殊字符)
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String originalExt = originalFilename.substring(originalFilename.lastIndexOf("."));
String originalOssKey = originalImage + uuid + originalExt;
String webpOssKey = thumbnailImage + uuid + ".webp";
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 3. 上传原始图片
try (InputStream inputStream = file.getInputStream()) {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(file.getContentType());
ossClient.putObject(bucketName, originalOssKey, inputStream, metadata);
// 4. 构造处理规则(关键:使用OSS专用Base64编码)
// 格式:image/format,webp|sys/saveas,o_<Base64编码的目标路径>,b_<Base64编码的存储桶>
String processRule = buildWebpSaveAsProcessRule(webpOssKey);
// 5. 执行处理
ProcessObjectRequest processRequest = new ProcessObjectRequest(bucketName, originalOssKey, processRule);
GenericResult result = ossClient.processObject(processRequest);
// 6. 验证处理成功
if (result.getResponse().getStatusCode() != 200) {
throw new RuntimeException("OSS生成WebP失败,状态码:" + result.getResponse().getStatusCode());
}
// 7. 返回WebP访问URL
OssFileRespVO ossFileRespVO = new OssFileRespVO();
ossFileRespVO.setOriginalUrl(domain + "/" + originalOssKey);
ossFileRespVO.setThumbnailUrl(domain + "/" + webpOssKey);
ossFileRespVO.setOriginalPath(originalOssKey);
ossFileRespVO.setThumbnailPath(webpOssKey);
return ossFileRespVO;
} catch (Exception e) {
log.error("上传文件失败", e);
throw new RuntimeException("上传文件失败");
} finally {
ossClient.shutdown();
}
}
/**
* 压缩图片并上传--调用oss--base64Data入参
*
* @param base64Data
* @return
*/
@Override
public String uploadZipBase64Method(String base64Data, String fileType) {
OssFileRespVO ossFileRespVO = uploadBase64AndConvertToWebp(base64Data, fileType);
return ossFileRespVO.getThumbnailUrl();
}
public String uploadZipBase64(String base64Data, String fileType) {
OssFileRespVO ossFileRespVO = uploadBase64AndConvertToWebp(base64Data, fileType);
log.info("=======返回图片地址是:{}======", ossFileRespVO.getOriginalUrl());
return ossFileRespVO.getOriginalUrl();
}
/**
* Base64 上传原图并由 OSS 转 WebP(带质量参数)
*/
private OssFileRespVO uploadBase64AndConvertToWebp(String base64Data, String fileType) {
ParsedBase64Image parsed = parseBase64Image(base64Data);
String uuid = UUID.randomUUID().toString().replace("-", "");
String originalOssKey = originalImage + uuid + parsed.extension;
String webpOssKey = thumbnailImage + uuid + ".webp";
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
try (InputStream inputStream = new ByteArrayInputStream(parsed.bytes)) {
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(parsed.contentType);
ossClient.putObject(bucketName, originalOssKey, inputStream, metadata);
String processRule = buildWebpSaveAsProcessRule(webpOssKey);
ProcessObjectRequest processRequest = new ProcessObjectRequest(bucketName, originalOssKey, processRule);
GenericResult result = ossClient.processObject(processRequest);
if (result.getResponse().getStatusCode() != 200) {
throw new RuntimeException("base64DataOSS生成WebP失败,状态码:" + result.getResponse().getStatusCode());
}
OssFileRespVO ossFileRespVO = new OssFileRespVO();
ossFileRespVO.setOriginalUrl(domain + "/" + originalOssKey);
ossFileRespVO.setThumbnailUrl(domain + "/" + webpOssKey);
ossFileRespVO.setOriginalPath(originalOssKey);
ossFileRespVO.setThumbnailPath(webpOssKey);
ossFileRespVO.setOriginalFilename(originalOssKey);
ossFileRespVO.setThumbnailFilename(webpOssKey);
return ossFileRespVO;
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
log.error("base64Data上传文件失败", e);
throw new RuntimeException("base64Data上传文件失败");
} finally {
ossClient.shutdown();
}
}
/**
* OSS 持久化转 WebP:先 quality 再 format(阿里云建议格式转换靠后)
*/
private String buildWebpSaveAsProcessRule(String webpOssKey) {
int quality = Math.min(100, Math.max(1, webpQuality));
String encodedKey = OSSBase64Utils.encode(webpOssKey);
String encodedBucket = OSSBase64Utils.encode(bucketName);
return String.format("image/quality,q_%d/format,webp|sys/saveas,o_%s,b_%s", quality, encodedKey, encodedBucket);
}
private ParsedBase64Image parseBase64Image(String base64Data) {
String contentType = null;
String payload = base64Data;
if (base64Data.startsWith("data:")) {
int comma = base64Data.indexOf(',');
if (comma < 0) {
throw new IllegalArgumentException("Base64 Data URL 格式非法");
}
String meta = base64Data.substring(5, comma);
int semi = meta.indexOf(';');
contentType = semi >= 0 ? meta.substring(0, semi) : meta;
payload = base64Data.substring(comma + 1);
}
byte[] bytes = Base64.getDecoder().decode(payload);
if (StrUtil.isBlank(contentType)) {
contentType = FileTypeUtils.getMineType(bytes);
}
String extension = extensionFromContentType(contentType);
return new ParsedBase64Image(bytes, contentType, extension);
}
private static String extensionFromContentType(String contentType) {
if (contentType == null) {
return ".jpg";
}
return switch (contentType) {
case "image/jpeg", "image/jpg" -> ".jpg";
case "image/png" -> ".png";
case "image/gif" -> ".gif";
case "image/bmp" -> ".bmp";
case "image/webp" -> ".webp";
default -> ".jpg";
};
}
private static final class ParsedBase64Image {
private final byte[] bytes;
private final String contentType;
private final String extension;
private ParsedBase64Image(byte[] bytes, String contentType, String extension) {
this.bytes = bytes;
this.contentType = contentType;
this.extension = extension;
}
}
}
八、Controller层
Java
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.encrypt.core.annotation.ApiEncrypt;
import cn.iocoder.yudao.module.infra.controller.admin.vo.*;
import cn.iocoder.yudao.module.infra.service.file.OssFileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.annotation.security.PermitAll;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - OSS文件存储")
@RestController
@RequestMapping("/infra/oss")
@Validated
@Slf4j
public class OssFileController {
@Resource
private OssFileService ossFileService;
@Value("${spring.servlet.multipart.max-file-size:200MB}")
private String maxFileSize;
@PostMapping("/upload")
@Operation(summary = "上传文件--返回永久URL")
@ApiEncrypt(request = false, response = false)
public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) {
long size = uploadReqVO.getFile().getSize();
//文件大小不能超过maxFileSize
if(size > Long.parseLong(maxFileSize.replaceAll("MB", "")) * 1024 * 1024){
return error(400, "文件大小不能超过" + maxFileSize);
}
String upload = ossFileService.uploadStr(uploadReqVO);
return success(upload);
}
// @PostMapping("/uploadByDTO")
// @Operation(summary = "上传文件--返回永久URL")
// public CommonResult<String> uploadByDTO(MultipartFile file) {
// FileUploadReqVO fileUploadReqVO = new FileUploadReqVO();
// fileUploadReqVO.setFile(file);
// String upload = ossFileService.uploadStr(fileUploadReqVO);
// return success(upload);
// }
@PostMapping("/upload-obj")
@Operation(summary = "上传文件--返回临时URL")
public CommonResult<SysFileRelationVo> uploadFileObj(FileUploadReqVO uploadReqVO) {
SysFileRelationVo upload = ossFileService.upload(uploadReqVO);
return success(upload);
}
@GetMapping("/url")
@Operation(summary = "获取文件URL--临时")
public CommonResult<String> getUrl(String file) {
String url = ossFileService.getUrl(file);
return success(url);
}
@PostMapping("/urls")
@Operation(summary = "批量获取文件URL--临时")
public CommonResult<List<FileBatchUrlsVO>> getUrls(@RequestBody List<String> fileNames) {
List<FileBatchUrlsVO> urls = ossFileService.getUrls(fileNames);
return success(urls);
}
@PostMapping("/urls-permanent")
@Operation(summary = "批量获取文件URL--永久")
public CommonResult<List<FileBatchUrlsVO>> getPermanentUrl(@RequestBody List<String> fileNames) {
List<FileBatchUrlsVO> urls = ossFileService.getPermanentUrl(fileNames);
return success(urls);
}
@PostMapping("/upload/file")
@Operation(summary = "上传文件file--返回永久URL")
public CommonResult<String> uploadFile(@RequestPart("file") MultipartFile file) {
FileUploadReqVO vo = new FileUploadReqVO();
vo.setFile(file);
vo.setPath(file.getOriginalFilename());
String upload = ossFileService.uploadStr(vo);
return success(upload);
}
@PostMapping("/uploadWxProfilePicture")
@Operation(summary = "微信上传头像文件--返回永久URL")
@PermitAll
public CommonResult<String> uploadWxProfilePicture(FileUploadReqVO uploadReqVO) {
String upload = ossFileService.uploadStr(uploadReqVO);
return success(upload);
}
@PostMapping("/uploadApk")
@Operation(summary = "上传apk文件--返回永久URL")
@ApiEncrypt(request = false, response = false)
public CommonResult<String> uploadFileApk(FileUploadReqVO uploadReqVO) {
long size = uploadReqVO.getFile().getSize();
//文件大小不能超过maxFileSize
if(size > Long.parseLong(maxFileSize.replaceAll("MB", "")) * 1024 * 1024){
return error(400, "文件大小不能超过" + maxFileSize);
}
String upload = ossFileService.uploadStrApk(uploadReqVO);
return success(upload);
}
@PostMapping("/upload/zip")
@Operation(summary = "上传文件并压缩--返回永久URL")
@ApiEncrypt(request = false, response = false)
public CommonResult<String> uploadFileZip(FileUploadReqVO uploadReqVO) {
long size = uploadReqVO.getFile().getSize();
//文件大小不能超过maxFileSize
if(size > Long.parseLong(maxFileSize.replaceAll("MB", "")) * 1024 * 1024){
return error(500, "文件大小不能超过" + maxFileSize);
}
OssFileRespVO ossFileRespVO = ossFileService.uploadZip(uploadReqVO);
return success(ossFileRespVO.getThumbnailUrl());
}
@PostMapping("/upload/zip1")
@Operation(summary = "上传文件并压缩--返回永久URL")
@ApiEncrypt(request = false, response = false)
public CommonResult<String> uploadFileZip(@RequestParam("file") MultipartFile file) {
long size = file.getSize();
//文件大小不能超过maxFileSize
if(size > Long.parseLong(maxFileSize.replaceAll("MB", "")) * 1024 * 1024){
return error(500, "文件大小不能超过" + maxFileSize);
}
String ossFileRespVO = ossFileService.uploadZipFile(file);
return success(ossFileRespVO);
}
@GetMapping("/base64")
@Operation(summary = "根据文字获取base64编码")
public CommonResult<String> base64(String text) {
// 编码水印内容
String encodedContent = Base64.getEncoder().encodeToString(text.getBytes(StandardCharsets.UTF_8))
.replace("+", "-").replace("/", "_").replace("=", "");
return success(encodedContent);
}
@PostMapping("/getUrlWatermark")
@Operation(summary = "getUrlWatermark:给王蔷")
@PermitAll
public String getUrlWatermark(@RequestBody GetUrlWatermarkReqVO getUrlWatermarkReqVO) {
String result = ossFileService.uploadZipBase64Method(getUrlWatermarkReqVO.getBase64Data(), "getUrlWatermark");
return result+"?x-oss-process=image/watermark,image_ZGlyLzczYTllMzk2M2YwMDQ0NTNiNjcyZTg2NTcwYmVjMzFiLnBuZw";
}
}
九、 阿里云oss配置
1、去阿里云创建bucket
2、在bucket下创建original_image(原图)和 thumbnail_image(压缩图)两个目录