🎨 规范文件上传参数

1. 规范文件上传参数
2. 产品模块接口调整
3. update forest.sql
4. update UserManual.md
This commit is contained in:
ronger 2024-03-14 08:25:28 +08:00 committed by GitHub
commit 661da90a34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 2890 additions and 253 deletions

View File

@ -16,7 +16,7 @@ git clone "https://github.com/rymcu/forest"
- `Redis v7.x +` - `Redis v7.x +`
### 手动搭建 MySQL 和 Redis 环境 ### 手动搭建 MySQL 和 Redis 环境
> 手动安装 MySQL 时,需初始化数据库。 > 手动安装 MySQL 时,需初始化数据库, sql 文件创建的用户密码都是 admin
在配置好 MySQL 和 Redis 的环境之后,在运行项目前,你还需要初始化好数据库中数据。通过执行 `src/main/resources/static` 在配置好 MySQL 和 Redis 的环境之后,在运行项目前,你还需要初始化好数据库中数据。通过执行 `src/main/resources/static`
目录下的 `forest.sql` 文件进行数据库初始化操作。 目录下的 `forest.sql` 文件进行数据库初始化操作。

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,14 @@
package com.rymcu.forest.enumerate;
/**
* Created on 2024/3/6 10:07.
*
* @author ronger
* @email ronger-x@outlook.com
* @desc : com.rymcu.forest.enumerate
*/
public class FileDataType {
public final static String URL = "0";
public final static String BASE64 = "1";
}

View File

@ -0,0 +1,38 @@
package com.rymcu.forest.enumerate;
import java.util.Arrays;
/**
* Created on 2024/3/6 10:51.
*
* @author ronger
* @email ronger-x@outlook.com
* @desc : com.rymcu.forest.enumerate
*/
public enum FilePath {
AVATAR,
ARTICLE,
TAG,
TOPIC,
PORTFOLIO,
PRODUCT,
IMAGES;
public static FilePath getFilePath(int type) {
for (FilePath filePath : FilePath.values()) {
if (filePath.ordinal() == type) {
return filePath;
}
}
return FilePath.IMAGES;
}
public static String getPath(int type) {
for (FilePath filePath : FilePath.values()) {
if (filePath.ordinal() == type) {
return filePath.name().toLowerCase();
}
}
return FilePath.IMAGES.name().toLowerCase();
}
}

View File

@ -8,6 +8,8 @@ import com.rymcu.forest.core.exception.UltraViresException;
import com.rymcu.forest.core.service.AbstractService; import com.rymcu.forest.core.service.AbstractService;
import com.rymcu.forest.dto.*; import com.rymcu.forest.dto.*;
import com.rymcu.forest.entity.Portfolio; import com.rymcu.forest.entity.Portfolio;
import com.rymcu.forest.enumerate.FilePath;
import com.rymcu.forest.enumerate.FileDataType;
import com.rymcu.forest.lucene.model.PortfolioLucene; import com.rymcu.forest.lucene.model.PortfolioLucene;
import com.rymcu.forest.lucene.util.PortfolioIndexUtil; import com.rymcu.forest.lucene.util.PortfolioIndexUtil;
import com.rymcu.forest.mapper.PortfolioMapper; import com.rymcu.forest.mapper.PortfolioMapper;
@ -16,7 +18,6 @@ import com.rymcu.forest.service.PortfolioService;
import com.rymcu.forest.service.UserService; import com.rymcu.forest.service.UserService;
import com.rymcu.forest.util.XssUtils; import com.rymcu.forest.util.XssUtils;
import com.rymcu.forest.web.api.common.UploadController; import com.rymcu.forest.web.api.common.UploadController;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -63,8 +64,8 @@ public class PortfolioServiceImpl extends AbstractService<Portfolio> implements
@Override @Override
public Portfolio postPortfolio(Portfolio portfolio) { public Portfolio postPortfolio(Portfolio portfolio) {
if (StringUtils.isNotBlank(portfolio.getHeadImgType())) { if (FileDataType.BASE64.equals(portfolio.getHeadImgType())) {
String headImgUrl = UploadController.uploadBase64File(portfolio.getHeadImgUrl(), 0); String headImgUrl = UploadController.uploadBase64File(portfolio.getHeadImgUrl(), FilePath.PORTFOLIO);
portfolio.setHeadImgUrl(headImgUrl); portfolio.setHeadImgUrl(headImgUrl);
} }
if (portfolio.getIdPortfolio() == null || portfolio.getIdPortfolio() == 0) { if (portfolio.getIdPortfolio() == null || portfolio.getIdPortfolio() == 0) {

View File

@ -3,11 +3,12 @@ package com.rymcu.forest.service.impl;
import com.rymcu.forest.core.service.AbstractService; import com.rymcu.forest.core.service.AbstractService;
import com.rymcu.forest.dto.ProductDTO; import com.rymcu.forest.dto.ProductDTO;
import com.rymcu.forest.entity.Product; import com.rymcu.forest.entity.Product;
import com.rymcu.forest.enumerate.FilePath;
import com.rymcu.forest.enumerate.FileDataType;
import com.rymcu.forest.mapper.ProductMapper; import com.rymcu.forest.mapper.ProductMapper;
import com.rymcu.forest.service.ProductService; import com.rymcu.forest.service.ProductService;
import com.rymcu.forest.util.BeanCopierUtil; import com.rymcu.forest.util.BeanCopierUtil;
import com.rymcu.forest.web.api.common.UploadController; import com.rymcu.forest.web.api.common.UploadController;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -49,8 +50,8 @@ public class ProductServiceImpl extends AbstractService<Product> implements Prod
@Override @Override
public Product postProduct(ProductDTO product) { public Product postProduct(ProductDTO product) {
boolean isUpdate = product.getIdProduct() > 0; boolean isUpdate = product.getIdProduct() > 0;
if (StringUtils.isNotBlank(product.getProductImgType())) { if (FileDataType.BASE64.equals(product.getProductImgType())) {
String headImgUrl = UploadController.uploadBase64File(product.getProductImgUrl(), 0); String headImgUrl = UploadController.uploadBase64File(product.getProductImgUrl(), FilePath.PRODUCT);
product.setProductImgUrl(headImgUrl); product.setProductImgUrl(headImgUrl);
} }
Product newProduct; Product newProduct;
@ -67,6 +68,7 @@ public class ProductServiceImpl extends AbstractService<Product> implements Prod
newProduct = new Product(); newProduct = new Product();
BeanCopierUtil.convert(product, newProduct); BeanCopierUtil.convert(product, newProduct);
newProduct.setCreatedTime(new Date()); newProduct.setCreatedTime(new Date());
productMapper.insertSelective(newProduct);
// 创建产品详情 // 创建产品详情
productMapper.insertProductContent(newProduct.getIdProduct(), product.getProductContent(), product.getProductContentHtml()); productMapper.insertProductContent(newProduct.getIdProduct(), product.getProductContent(), product.getProductContentHtml());
} }

View File

@ -10,6 +10,7 @@ import com.rymcu.forest.dto.ArticleTagDTO;
import com.rymcu.forest.dto.LabelModel; import com.rymcu.forest.dto.LabelModel;
import com.rymcu.forest.entity.Article; import com.rymcu.forest.entity.Article;
import com.rymcu.forest.entity.Tag; import com.rymcu.forest.entity.Tag;
import com.rymcu.forest.enumerate.FilePath;
import com.rymcu.forest.mapper.ArticleMapper; import com.rymcu.forest.mapper.ArticleMapper;
import com.rymcu.forest.mapper.TagMapper; import com.rymcu.forest.mapper.TagMapper;
import com.rymcu.forest.service.TagService; import com.rymcu.forest.service.TagService;
@ -126,7 +127,7 @@ public class TagServiceImpl extends AbstractService<Tag> implements TagService {
} }
} }
if (StringUtils.isNotBlank(tag.getTagIconPath()) && tag.getTagIconPath().contains("base64")) { if (StringUtils.isNotBlank(tag.getTagIconPath()) && tag.getTagIconPath().contains("base64")) {
String tagIconPath = UploadController.uploadBase64File(tag.getTagIconPath(), 2); String tagIconPath = UploadController.uploadBase64File(tag.getTagIconPath(), FilePath.TAG);
tag.setTagIconPath(tagIconPath); tag.setTagIconPath(tagIconPath);
} else { } else {
tag.setTagIconPath(tag.getTagIconPath()); tag.setTagIconPath(tag.getTagIconPath());
@ -137,7 +138,7 @@ public class TagServiceImpl extends AbstractService<Tag> implements TagService {
} else { } else {
tag.setUpdatedTime(new Date()); tag.setUpdatedTime(new Date());
if (StringUtils.isNotBlank(tag.getTagIconPath()) && tag.getTagIconPath().contains("base64")) { if (StringUtils.isNotBlank(tag.getTagIconPath()) && tag.getTagIconPath().contains("base64")) {
String tagIconPath = UploadController.uploadBase64File(tag.getTagIconPath(), 2); String tagIconPath = UploadController.uploadBase64File(tag.getTagIconPath(), FilePath.TAG);
tag.setTagIconPath(tagIconPath); tag.setTagIconPath(tagIconPath);
} }
result = tagMapper.update(tag.getIdTag(), tag.getTagUri(), tag.getTagIconPath(), tag.getTagStatus(), tag.getTagDescription(), tag.getTagReservation()); result = tagMapper.update(tag.getIdTag(), tag.getTagUri(), tag.getTagIconPath(), tag.getTagStatus(), tag.getTagDescription(), tag.getTagReservation());

View File

@ -8,6 +8,7 @@ import com.rymcu.forest.dto.admin.TopicDTO;
import com.rymcu.forest.dto.admin.TopicTagDTO; import com.rymcu.forest.dto.admin.TopicTagDTO;
import com.rymcu.forest.entity.Tag; import com.rymcu.forest.entity.Tag;
import com.rymcu.forest.entity.Topic; import com.rymcu.forest.entity.Topic;
import com.rymcu.forest.enumerate.FilePath;
import com.rymcu.forest.mapper.TopicMapper; import com.rymcu.forest.mapper.TopicMapper;
import com.rymcu.forest.service.TopicService; import com.rymcu.forest.service.TopicService;
import com.rymcu.forest.util.XssUtils; import com.rymcu.forest.util.XssUtils;
@ -59,7 +60,7 @@ public class TopicServiceImpl extends AbstractService<Topic> implements TopicSer
} }
} }
if (StringUtils.isNotBlank(topic.getTopicIconPath()) && topic.getTopicIconPath().contains("base64")) { if (StringUtils.isNotBlank(topic.getTopicIconPath()) && topic.getTopicIconPath().contains("base64")) {
String topicIconPath = UploadController.uploadBase64File(topic.getTopicIconPath(), 3); String topicIconPath = UploadController.uploadBase64File(topic.getTopicIconPath(), FilePath.TOPIC);
topic.setTopicIconPath(topicIconPath); topic.setTopicIconPath(topicIconPath);
} else { } else {
topic.setTopicIconPath(topic.getTopicIconPath()); topic.setTopicIconPath(topic.getTopicIconPath());
@ -74,7 +75,7 @@ public class TopicServiceImpl extends AbstractService<Topic> implements TopicSer
result = topicMapper.insertSelective(topic); result = topicMapper.insertSelective(topic);
} else { } else {
if (StringUtils.isNotBlank(topic.getTopicIconPath()) && topic.getTopicIconPath().contains("base64")) { if (StringUtils.isNotBlank(topic.getTopicIconPath()) && topic.getTopicIconPath().contains("base64")) {
String topicIconPath = UploadController.uploadBase64File(topic.getTopicIconPath(), 3); String topicIconPath = UploadController.uploadBase64File(topic.getTopicIconPath(), FilePath.TOPIC);
topic.setTopicIconPath(topicIconPath); topic.setTopicIconPath(topicIconPath);
} }
topic.setUpdatedTime(new Date()); topic.setUpdatedTime(new Date());

View File

@ -9,6 +9,8 @@ import com.rymcu.forest.dto.*;
import com.rymcu.forest.entity.Role; import com.rymcu.forest.entity.Role;
import com.rymcu.forest.entity.User; import com.rymcu.forest.entity.User;
import com.rymcu.forest.entity.UserExtend; import com.rymcu.forest.entity.UserExtend;
import com.rymcu.forest.enumerate.FilePath;
import com.rymcu.forest.enumerate.FileDataType;
import com.rymcu.forest.lucene.model.UserLucene; import com.rymcu.forest.lucene.model.UserLucene;
import com.rymcu.forest.lucene.util.UserIndexUtil; import com.rymcu.forest.lucene.util.UserIndexUtil;
import com.rymcu.forest.mapper.RoleMapper; import com.rymcu.forest.mapper.RoleMapper;
@ -191,8 +193,8 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
if (number > 0) { if (number > 0) {
throw new NicknameOccupyException("该昵称已使用!"); throw new NicknameOccupyException("该昵称已使用!");
} }
if (StringUtils.isNotBlank(user.getAvatarType()) && AVATAR_SVG_TYPE.equals(user.getAvatarType())) { if (FileDataType.BASE64.equals(user.getAvatarType())) {
String avatarUrl = UploadController.uploadBase64File(user.getAvatarUrl(), 0); String avatarUrl = UploadController.uploadBase64File(user.getAvatarUrl(), FilePath.AVATAR);
user.setAvatarUrl(avatarUrl); user.setAvatarUrl(avatarUrl);
user.setAvatarType("0"); user.setAvatarType("0");
} }

View File

@ -6,6 +6,7 @@ import com.rymcu.forest.core.result.GlobalResult;
import com.rymcu.forest.core.result.GlobalResultGenerator; import com.rymcu.forest.core.result.GlobalResultGenerator;
import com.rymcu.forest.dto.LinkToImageUrlDTO; import com.rymcu.forest.dto.LinkToImageUrlDTO;
import com.rymcu.forest.dto.TokenUser; import com.rymcu.forest.dto.TokenUser;
import com.rymcu.forest.enumerate.FilePath;
import com.rymcu.forest.service.ForestFileService; import com.rymcu.forest.service.ForestFileService;
import com.rymcu.forest.util.FileUtils; import com.rymcu.forest.util.FileUtils;
import com.rymcu.forest.util.SpringContextHolder; import com.rymcu.forest.util.SpringContextHolder;
@ -29,6 +30,7 @@ import java.io.*;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.*; import java.util.*;
import com.rymcu.forest.util.SSRFUtil; import com.rymcu.forest.util.SSRFUtil;
/** /**
@ -48,38 +50,18 @@ public class UploadController {
@Resource @Resource
private ForestFileService forestFileService; private ForestFileService forestFileService;
private static String getTypePath(Integer type) { public static String uploadBase64File(String fileStr, FilePath filePath) {
String typePath;
switch (type) {
case 0:
typePath = "avatar";
break;
case 1:
typePath = "article";
break;
case 2:
typePath = "tag";
break;
case 3:
typePath = "topic";
break;
default:
typePath = "images";
}
return typePath;
}
public static String uploadBase64File(String fileStr, Integer type) {
if (StringUtils.isBlank(fileStr)) { if (StringUtils.isBlank(fileStr)) {
return ""; return "";
} }
String typePath = getTypePath(type); String typePath = filePath.name().toLowerCase();
//图片存储路径 //图片存储路径
String ctxHeadPicPath = env.getProperty("resource.pic-path"); String ctxHeadPicPath = env.getProperty("resource.pic-path");
String dir = ctxHeadPicPath + "/" + typePath; String dir = ctxHeadPicPath + "/" + typePath;
File file = new File(dir); File file = new File(dir);
if (!file.exists()) { if (!file.exists()) {
file.mkdirs();// 创建文件根目录 // 创建文件根目录
file.mkdirs();
} }
String localPath = Utils.getProperty("resource.file-path") + "/" + typePath + "/"; String localPath = Utils.getProperty("resource.file-path") + "/" + typePath + "/";
@ -98,9 +80,9 @@ public class UploadController {
/** /**
* 从输入流中获取字节数组 * 从输入流中获取字节数组
* *
* @param inputStream * @param inputStream 输入流
* @return * @return byte[]
* @throws IOException * @throws IOException IO 异常
*/ */
public static byte[] readInputStream(InputStream inputStream) throws IOException { public static byte[] readInputStream(InputStream inputStream) throws IOException {
byte[] buffer = new byte[1024]; byte[] buffer = new byte[1024];
@ -134,20 +116,10 @@ public class UploadController {
data.put("url", fileUrl); data.put("url", fileUrl);
return GlobalResultGenerator.genSuccessResult(data); return GlobalResultGenerator.genSuccessResult(data);
} }
String typePath = getTypePath(type); File file = genFile(type);
//图片存储路径 String typePath = FilePath.getPath(type);
String ctxHeadPicPath = env.getProperty("resource.pic-path");
String dir = ctxHeadPicPath + "/" + typePath;
File file = new File(dir);
if (!file.exists()) {
file.mkdirs();// 创建文件根目录
}
String localPath = Utils.getProperty("resource.file-path") + "/" + typePath + "/"; String localPath = Utils.getProperty("resource.file-path") + "/" + typePath + "/";
String fileName = System.currentTimeMillis() + fileType; String fileName = System.currentTimeMillis() + fileType;
String savePath = file.getPath() + File.separator + fileName; String savePath = file.getPath() + File.separator + fileName;
fileUrl = localPath + fileName; fileUrl = localPath + fileName;
File saveFile = new File(savePath); File saveFile = new File(savePath);
@ -162,11 +134,8 @@ public class UploadController {
} }
@PostMapping("/file/batch") private File genFile(Integer type) {
@Transactional(rollbackFor = Exception.class) String typePath = FilePath.getPath(type);
public GlobalResult<JSONObject> batchFileUpload(@RequestParam(value = "file[]", required = false) MultipartFile[] multipartFiles, @RequestParam(defaultValue = "1") Integer type, HttpServletRequest request) {
TokenUser tokenUser = getTokenUser(request);
String typePath = getTypePath(type);
//图片存储路径 //图片存储路径
String ctxHeadPicPath = env.getProperty("resource.pic-path"); String ctxHeadPicPath = env.getProperty("resource.pic-path");
String dir = ctxHeadPicPath + "/" + typePath; String dir = ctxHeadPicPath + "/" + typePath;
@ -174,13 +143,20 @@ public class UploadController {
if (!file.exists()) { if (!file.exists()) {
file.mkdirs();// 创建文件根目录 file.mkdirs();// 创建文件根目录
} }
return file;
}
@PostMapping("/file/batch")
@Transactional(rollbackFor = Exception.class)
public GlobalResult<JSONObject> batchFileUpload(@RequestParam(value = "file[]", required = false) MultipartFile[] multipartFiles, @RequestParam(defaultValue = "1") Integer type, HttpServletRequest request) {
TokenUser tokenUser = getTokenUser(request);
File file = genFile(type);
String typePath = FilePath.getPath(type);
String localPath = Utils.getProperty("resource.file-path") + "/" + typePath + "/"; String localPath = Utils.getProperty("resource.file-path") + "/" + typePath + "/";
Map successMap = new HashMap(16); Map<String, String> successMap = new HashMap<>(16);
Set errFiles = new HashSet(); Set<String> errFiles = new HashSet<>();
for (int i = 0, len = multipartFiles.length; i < len; i++) { for (MultipartFile multipartFile : multipartFiles) {
MultipartFile multipartFile = multipartFiles[i];
String orgName = multipartFile.getOriginalFilename(); String orgName = multipartFile.getOriginalFilename();
if (multipartFile.getSize() == 0) { if (multipartFile.getSize() == 0) {
@ -247,12 +223,10 @@ public class UploadController {
@PostMapping("/file/link") @PostMapping("/file/link")
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public GlobalResult linkToImageUrl(@RequestBody LinkToImageUrlDTO linkToImageUrlDTO, HttpServletRequest request) throws IOException { public GlobalResult<Map<String, String>> linkToImageUrl(@RequestBody LinkToImageUrlDTO linkToImageUrlDTO, HttpServletRequest request) throws IOException {
TokenUser tokenUser = getTokenUser(request); TokenUser tokenUser = getTokenUser(request);
String url = linkToImageUrlDTO.getUrl(); String url = linkToImageUrlDTO.getUrl();
Map data = new HashMap(2); Map<String, String> data = new HashMap<>(2);
if (StringUtils.isBlank(url)) { if (StringUtils.isBlank(url)) {
data.put("message", "文件为空!"); data.put("message", "文件为空!");
return GlobalResultGenerator.genSuccessResult(data); return GlobalResultGenerator.genSuccessResult(data);
@ -293,19 +267,12 @@ public class UploadController {
data.put("url", fileUrl); data.put("url", fileUrl);
return GlobalResultGenerator.genSuccessResult(data); return GlobalResultGenerator.genSuccessResult(data);
} }
Integer type = linkToImageUrlDTO.getType(); Integer type = linkToImageUrlDTO.getType();
if (Objects.isNull(type)) { if (Objects.isNull(type)) {
type = 1; type = 1;
} }
String typePath = getTypePath(type); File file = genFile(type);
//图片存储路径 String typePath = FilePath.getPath(type);
String ctxHeadPicPath = env.getProperty("resource.pic-path");
String dir = ctxHeadPicPath + "/" + typePath;
File file = new File(dir);
if (!file.exists()) {
file.mkdirs();// 创建文件根目录
}
String fileName = System.currentTimeMillis() + fileType; String fileName = System.currentTimeMillis() + fileType;
fileUrl = Utils.getProperty("resource.file-path") + "/" + typePath + "/" + fileName; fileUrl = Utils.getProperty("resource.file-path") + "/" + typePath + "/" + fileName;
@ -318,9 +285,7 @@ public class UploadController {
data.put("url", fileUrl); data.put("url", fileUrl);
return GlobalResultGenerator.genSuccessResult(data); return GlobalResultGenerator.genSuccessResult(data);
} catch (IOException e) { } catch (IOException e) {
/** // 上传失败返回原链接
* 上传失败返回原链接
*/
logger.error("link: {},\nmessage: {}", url, e.getMessage()); logger.error("link: {},\nmessage: {}", url, e.getMessage());
data.put("originalURL", url); data.put("originalURL", url);
data.put("url", url); data.put("url", url);

File diff suppressed because it is too large Load Diff