package com.ruoyi.basic.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.basic.dto.StorageBlobVO;
|
import com.ruoyi.basic.mapper.StorageBlobMapper;
|
import com.ruoyi.basic.pojo.StorageBlob;
|
import com.ruoyi.basic.service.StorageBlobService;
|
import com.ruoyi.basic.utils.FileUtil;
|
import com.ruoyi.common.config.FileProperties;
|
import io.jsonwebtoken.Claims;
|
import io.jsonwebtoken.Jwts;
|
import io.jsonwebtoken.security.Keys;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.multipart.MultipartFile;
|
|
import javax.crypto.SecretKey;
|
import java.io.File;
|
import java.io.IOException;
|
import java.nio.charset.StandardCharsets;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.UUID;
|
|
/**
|
* <p>
|
* 通用文件上传的附件信息 服务实现类
|
* </p>
|
*
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class StorageBlobServiceImpl extends ServiceImpl<StorageBlobMapper, StorageBlob> implements StorageBlobService {
|
private final FileProperties properties;
|
private final StorageBlobMapper storageBlobMapper;
|
private final FileUtil fileUtil;
|
|
@Override
|
public List<StorageBlobVO> upload(List<MultipartFile> files) {
|
if (CollectionUtils.isEmpty(files)) {
|
throw new IllegalArgumentException("文件不能为空");
|
}
|
|
List<StorageBlobVO> storageBlobVOS = new ArrayList<>();
|
|
for (MultipartFile file : files) {
|
if (file == null || file.isEmpty()) {
|
throw new IllegalArgumentException("文件不能为空");
|
}
|
|
String originalFileName = StringUtils.hasText(file.getOriginalFilename())
|
? StringUtils.cleanPath(file.getOriginalFilename())
|
: UUID.randomUUID().toString();
|
String fileName = UUID.randomUUID() + "_" + originalFileName;
|
String relativePath = fileUtil.buildRelativePath();
|
File targetDirectory = new File(properties.getPath(), relativePath);
|
if (!targetDirectory.exists() && !targetDirectory.mkdirs()) {
|
throw new RuntimeException("创建上传目录失败");
|
}
|
File dest = new File(targetDirectory, fileName);
|
|
StorageBlobVO storageBlob;
|
try {
|
file.transferTo(dest);
|
storageBlob = getStorageBlob(file, originalFileName, fileName, relativePath);
|
if (storageBlob == null || storageBlob.getId() == null) {
|
throw new RuntimeException("文件元数据保存失败");
|
}
|
} catch (RuntimeException e) {
|
if (dest.exists()) {
|
dest.delete();
|
}
|
throw e;
|
} catch (IOException e) {
|
throw new RuntimeException("文件保存失败", e);
|
}
|
|
storageBlobVOS.add(storageBlob);
|
}
|
return storageBlobVOS;
|
}
|
|
@Override
|
public File getFileByToken(String fileName, String token) {
|
if (!StringUtils.hasText(token)) {
|
throw new IllegalArgumentException("token不能为空");
|
}
|
|
String secretStr = StringUtils.hasText(properties.getJwtSecret())
|
? properties.getJwtSecret()
|
: "local-file-jwt-secret";
|
|
SecretKey key = Keys.hmacShaKeyFor(secretStr.getBytes(StandardCharsets.UTF_8));
|
Claims claims = Jwts.parser()
|
.verifyWith(key) // 代替旧版的 setSigningKey
|
.build() // 必须先构建解析器
|
.parseSignedClaims(token) // 代替旧版的 parseClaimsJws
|
.getPayload(); // 代替旧版的 getBody()
|
if (!fileName.equals(claims.getSubject())) {
|
throw new IllegalArgumentException("token与文件不匹配");
|
}
|
fileUtil.validateTokenUsage(token);
|
StorageBlob storageBlob = findStorageBlob(fileName);
|
String path = storageBlob == null ? claims.get("path", String.class) : storageBlob.getPath();
|
if (!StringUtils.hasText(path)) {
|
return new File(properties.getPath(), fileName);
|
}
|
return new File(new File(properties.getPath(), path), fileName);
|
}
|
|
private StorageBlob findStorageBlob(String fileName) {
|
return storageBlobMapper.selectOne(new LambdaQueryWrapper<StorageBlob>()
|
.eq(StorageBlob::getUidFilename, fileName)
|
.last("limit 1"));
|
}
|
|
private StorageBlobVO getStorageBlob(MultipartFile file, String originalFileName, String fileName, String relativePath) {
|
StorageBlobVO storageBlob = new StorageBlobVO();
|
storageBlob.setResourceKey(UUID.randomUUID().toString().replace("-", ""));
|
storageBlob.setContentType(file.getContentType());
|
storageBlob.setOriginalFilename(originalFileName);
|
storageBlob.setUidFilename(fileName);
|
storageBlob.setByteSize(file.getSize());
|
storageBlob.setPath(relativePath);
|
storageBlob.setPreviewURL(fileUtil.buildSignedPreviewUrl(storageBlob));
|
storageBlob.setDownloadURL(fileUtil.buildSignedDownloadUrl(storageBlob));
|
int affectedRows = storageBlobMapper.insert(storageBlob);
|
if (affectedRows <= 0) {
|
throw new RuntimeException("文件元数据保存失败");
|
}
|
return storageBlob;
|
}
|
|
@Override
|
public String getDownloadFileName(String fileName) {
|
StorageBlob storageBlob = findStorageBlob(fileName);
|
if (storageBlob == null || !StringUtils.hasText(storageBlob.getOriginalFilename())) {
|
return fileName;
|
}
|
return storageBlob.getOriginalFilename();
|
}
|
}
|