强化文件api,添加FilePond

This commit is contained in:
AlanScipio
2024-02-22 11:19:57 +08:00
parent da8d9f2fed
commit 7b71fd28e4
57 changed files with 1798 additions and 1542 deletions

View File

@@ -59,12 +59,6 @@
<artifactId>minio</artifactId>
<version>${minio.version}</version>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId>
</dependency>
<!-- Mysql Connector -->
<dependency>
@@ -82,6 +76,12 @@
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-services</artifactId>
<!-- <exclusions>-->
<!-- <exclusion>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <artifactId>ruoyi-common-log</artifactId>-->
<!-- </exclusion>-->
<!-- </exclusions>-->
</dependency>
<!-- RuoYi Common Datasource-->
@@ -89,7 +89,19 @@
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
</dependency>
<!-- RuoYi Common Core -->
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <artifactId>ruoyi-common-security</artifactId>-->
<!-- </dependency>-->
<!-- &lt;!&ndash; 系统接口 &ndash;&gt;-->
<!-- <dependency>-->
<!-- <groupId>com.ruoyi</groupId>-->
<!-- <artifactId>ruoyi-api-system</artifactId>-->
<!-- </dependency>-->
</dependencies>
<build>

View File

@@ -1,5 +1,6 @@
package com.ruoyi.file;
import com.ruoyi.common.security.annotation.EnableRyFeignClients;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -13,6 +14,7 @@ import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
*/
@ConditionalOnProperty(name = "spring.cloud.nacos.config.group", havingValue = "DEFAULT_GROUP", matchIfMissing = true)
@EnableCustomSwagger2
@EnableRyFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class RuoYiFileApplication {
public static void main(String[] args) {

View File

@@ -4,6 +4,8 @@ import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.file.domain.SysFile;
import com.ruoyi.file.service.ISysFileCRUDService;
@@ -43,6 +45,10 @@ public class SysFileCRUDController extends BaseController {
@PostMapping("/export")
public void export(HttpServletResponse response, SysFile sysFile) {
List<SysFile> list = crudService.selectSysFileList(sysFile);
if (list.isEmpty()) {
responseJsonWarn(response, "没有数据可以导出");
return;
}
ExcelUtil<SysFile> util = new ExcelUtil<>(SysFile.class);
util.exportExcel(response, list, "文件存储记录数据");
}
@@ -55,4 +61,34 @@ public class SysFileCRUDController extends BaseController {
public AjaxResult getInfo(@PathVariable("fileId") String fileId) {
return success(crudService.selectSysFileByFileId(fileId));
}
/**
* 新增文件存储记录
*/
@RequiresPermissions("wms:FileRecord:add")
@Log(title = "文件存储记录", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody SysFile sysFile) {
return toAjax(crudService.insertSysFile(sysFile));
}
/**
* 修改文件存储记录
*/
@RequiresPermissions("wms:FileRecord:edit")
@Log(title = "文件存储记录", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody SysFile sysFile) {
return toAjax(crudService.updateSysFile(sysFile));
}
/**
* 删除文件存储记录
*/
@RequiresPermissions("wms:FileRecord:remove")
@Log(title = "文件存储记录", businessType = BusinessType.DELETE)
@DeleteMapping("/{fileIds}")
public AjaxResult remove(@PathVariable String[] fileIds) throws Exception {
return toAjax(crudService.deleteSysFileByFileIds(fileIds));
}
}

View File

@@ -1,9 +1,10 @@
package com.ruoyi.file.controller;
import com.ruoyi.file.domain.FileSaveResult;
import com.ruoyi.file.domain.FileResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@@ -32,7 +33,7 @@ public class SysFileController {
public R<SysFileInfo> upload(MultipartFile file) {
try {
// 上传并返回访问地址
FileSaveResult saveResult = sysFileService.uploadFile(file);
FileResult saveResult = sysFileService.uploadFile(file);
String requestUrl = saveResult.getRequestUrl();
// 构建返回结果
SysFileInfo responseInfo = new SysFileInfo();
@@ -45,4 +46,18 @@ public class SysFileController {
return R.fail(e.getMessage());
}
}
/**
* 删除文件
*/
@PostMapping("deleteFiles/{fileIds}")
public R<SysFileInfo> deleteFiles(@PathVariable String[] fileIds) {
try {
FileResult fileResult = sysFileService.deleteFiles(fileIds);
return fileResult.isSuccess() ? R.ok() : R.fail(fileResult.getMessage("删除文件失败"));
} catch (Exception e) {
log.error("删除文件失败", e);
return R.fail(e.getMessage());
}
}
}

View File

@@ -1,5 +1,6 @@
package com.ruoyi.file.domain;
import com.ruoyi.common.core.utils.StringUtils;
import lombok.Data;
import java.io.Serial;
@@ -10,7 +11,7 @@ import java.io.Serializable;
* created on 2024/2/19
*/
@Data
public class FileSaveResult implements Serializable {
public class FileResult implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@@ -19,6 +20,8 @@ public class FileSaveResult implements Serializable {
private String message;
private int count;
/**
* 文件请求地址
*/
@@ -33,19 +36,30 @@ public class FileSaveResult implements Serializable {
return uploadResult == null ? "" : uploadResult.getFileId();
}
public static FileSaveResult success(String requestUrl, FileUploadResult uploadResult) {
FileSaveResult result = new FileSaveResult();
public static FileResult success(String requestUrl, FileUploadResult uploadResult) {
FileResult result = new FileResult();
result.setSuccess(true);
result.setRequestUrl(requestUrl);
result.setUploadResult(uploadResult);
return result;
}
public static FileSaveResult fail(String message) {
FileSaveResult result = new FileSaveResult();
public static FileResult success(String requestUrl) {
return success(requestUrl, null);
}
public static FileResult success() {
return success(null, null);
}
public static FileResult fail(String message) {
FileResult result = new FileResult();
result.setSuccess(false);
result.setMessage(message);
return result;
}
public String getMessage(String defaultMessage) {
return StringUtils.isBlank(message) ? defaultMessage : message;
}
}

View File

@@ -1,7 +1,7 @@
package com.ruoyi.file.service;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.ruoyi.file.domain.FileSaveResult;
import com.ruoyi.file.domain.FileResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@@ -29,12 +29,17 @@ public class FastDfsSysFileServiceImpl implements ISysFileService {
* @return 访问地址
*/
@Override
public FileSaveResult uploadFile(MultipartFile file) throws Exception {
public FileResult uploadFile(MultipartFile file) throws Exception {
// InputStream inputStream = file.getInputStream();
// StorePath storePath = storageClient.uploadFile(inputStream, file.getSize(),
// FileTypeUtils.getExtension(file), null);
// IoUtils.closeQuietly(inputStream);
// return domain + "/" + storePath.getFullPath();
return FileSaveResult.fail("Not implemented yet!");
return FileResult.fail("Not implemented yet!");
}
@Override
public FileResult deleteFiles(String[] fileIds) throws Exception {
return FileResult.fail("Not implemented yet!");
}
}

View File

@@ -49,7 +49,7 @@ public interface ISysFileCRUDService {
* @param fileIds 需要删除的文件存储记录主键集合
* @return 结果
*/
int deleteSysFileByFileIds(String[] fileIds);
int deleteSysFileByFileIds(String[] fileIds) throws Exception;
/**
* 删除文件存储记录信息
@@ -57,5 +57,5 @@ public interface ISysFileCRUDService {
* @param fileId 文件存储记录主键
* @return 结果
*/
int deleteSysFileByFileId(String fileId);
int deleteSysFileByFileId(String fileId) throws Exception;
}

View File

@@ -1,8 +1,16 @@
package com.ruoyi.file.service;
import com.ruoyi.file.domain.FileSaveResult;
import com.ruoyi.file.domain.FileResult;
import com.ruoyi.file.domain.SysFile;
import com.ruoyi.file.mapper.SysFileDynamicSqlSupport;
import com.ruoyi.file.mapper.SysFileMapper;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* 文件上传接口
*
@@ -15,6 +23,26 @@ public interface ISysFileService {
* @param file 上传的文件
* @return 保存结果
*/
FileSaveResult uploadFile(MultipartFile file) throws Exception;
FileResult uploadFile(MultipartFile file) throws Exception;
/**
* 删除文件
*
* @param fileIds 文件id
*/
FileResult deleteFiles(String[] fileIds) throws Exception;
default List<SysFile> selectFilesById(SysFileMapper sysFileMapper, String[] fileIds) {
if (fileIds == null || fileIds.length == 0) {
throw new IllegalArgumentException("file ids is empty");
}
SelectStatementProvider provider = SqlBuilder.select(SysFileMapper.selectList)
.from(SysFileDynamicSqlSupport.sysFile)
.where(SysFileDynamicSqlSupport.fileId, SqlBuilder.isIn(fileIds))
.orderBy(SysFileDynamicSqlSupport.fileId)
.build()
.render(RenderingStrategies.MYBATIS3);
return sysFileMapper.selectMany(provider);
}
}

View File

@@ -1,7 +1,9 @@
package com.ruoyi.file.service;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.file.constants.FileStorageType;
import com.ruoyi.file.domain.FileSaveResult;
import com.ruoyi.file.domain.FileResult;
import com.ruoyi.file.domain.FileUploadResult;
import com.ruoyi.file.domain.SysFile;
import com.ruoyi.file.mapper.SysFileMapper;
@@ -13,6 +15,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* 本地文件存储
*
@@ -50,19 +56,55 @@ public class LocalSysFileServiceImpl implements ISysFileService {
*/
@Transactional
@Override
public FileSaveResult uploadFile(MultipartFile file) throws Exception {
public FileResult uploadFile(MultipartFile file) throws Exception {
// 保存文件到本地
FileUploadResult uploadResult = FileUploadUtils.upload(localFilePath, file);
String savedPathFileName = uploadResult.getSavedPathFileName();
String requestUrl = domain + localFilePrefix + savedPathFileName;
// 保存文件记录
SysFile record = getSysFile(uploadResult, requestUrl);
SysFile record = buildRecord(uploadResult, requestUrl);
sysFileMapper.insertSelective(record);
// 返回访问地址
return FileSaveResult.success(requestUrl, uploadResult);
return FileResult.success(requestUrl, uploadResult);
}
private SysFile getSysFile(FileUploadResult uploadResult, String requestUrl) {
/**
* 本地文件删除
*
* @param fileIds 文件id
* @return 删除结果
*/
@Transactional
@Override
public FileResult deleteFiles(String[] fileIds) {
// 查询文件记录
List<SysFile> fileList = selectFilesById(sysFileMapper, fileIds);
// 删除文件
List<String> warningList = new ArrayList<>();
for (SysFile sysFile : fileList) {
File file = new File(sysFile.getFilePath());
if (file.exists()) {
if (file.delete()) {
sysFileMapper.deleteByPrimaryKey(sysFile.getFileId());
} else {
throw new ServiceException("Delete file failed: [" + sysFile.getFilePath() + "]", HttpStatus.ERROR);
}
} else {
warningList.add(sysFile.getFilePath());
}
}
// 组装返回结果
FileResult result = FileResult.success();
if (!warningList.isEmpty()) {
result.setMessage("Files not exists: " + warningList);
} else {
result.setMessage("Delete file success");
}
result.setCount(fileList.size() - warningList.size());
return result;
}
private SysFile buildRecord(FileUploadResult uploadResult, String requestUrl) {
SysFile record = new SysFile();
record.setFileId(uploadResult.getFileId()); // 文件ID
record.setSavedName(uploadResult.getSavedFileName()); // 保存的文件名

View File

@@ -1,17 +1,12 @@
package com.ruoyi.file.service;
import com.alibaba.nacos.common.utils.IoUtils;
import com.ruoyi.file.domain.FileSaveResult;
import com.ruoyi.file.utils.FileUploadUtils;
import com.ruoyi.file.config.MinioConfig;
import com.ruoyi.file.domain.FileResult;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.InputStream;
/**
* TODO 未完成,还需要改造:保存文件记录
* Minio 文件存储
@@ -33,18 +28,24 @@ public class MinioSysFileServiceImpl implements ISysFileService {
* @return 访问地址
*/
@Override
public FileSaveResult uploadFile(MultipartFile file) throws Exception {
String fileName = FileUploadUtils.extractFilename(file, null);
InputStream inputStream = file.getInputStream();
PutObjectArgs args = PutObjectArgs.builder()
.bucket(minioConfig.getBucketName())
.object(fileName)
.stream(inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build();
client.putObject(args);
IoUtils.closeQuietly(inputStream);
String requestUrl = minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
return FileSaveResult.success(requestUrl, null);
public FileResult uploadFile(MultipartFile file) throws Exception {
// String fileName = FileUploadUtils.extractFilename(file, null);
// InputStream inputStream = file.getInputStream();
// PutObjectArgs args = PutObjectArgs.builder()
// .bucket(minioConfig.getBucketName())
// .object(fileName)
// .stream(inputStream, file.getSize(), -1)
// .contentType(file.getContentType())
// .build();
// client.putObject(args);
// IoUtils.closeQuietly(inputStream);
// String requestUrl = minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
// return FileResult.success(requestUrl, null);
return FileResult.fail("Not implemented yet!");
}
@Override
public FileResult deleteFiles(String[] fileIds) throws Exception {
return FileResult.fail("Not implemented yet!");
}
}

View File

@@ -1,11 +1,11 @@
package com.ruoyi.file.service;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.file.domain.FileResult;
import com.ruoyi.file.domain.SysFile;
import com.ruoyi.file.mapper.SysFileDynamicSqlSupport;
import com.ruoyi.file.mapper.SysFileMapper;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.mybatis.dynamic.sql.select.SelectDSLCompleter;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
@@ -24,9 +24,13 @@ import java.util.Optional;
*/
@Service
public class SysFileCRUDServiceImpl implements ISysFileCRUDService {
@Autowired
private SysFileMapper sysFileMapper;
@Autowired
private ISysFileService sysFileService;
/**
* 查询文件存储记录
*
@@ -52,13 +56,15 @@ public class SysFileCRUDServiceImpl implements ISysFileCRUDService {
SelectStatementProvider provider = SqlBuilder.select(SysFileMapper.selectList)
.from(SysFileDynamicSqlSupport.sysFile)
.where(SysFileDynamicSqlSupport.fileId, SqlBuilder.isEqualToWhenPresent(sysFile.getFileId()))
.and(SysFileDynamicSqlSupport.savedName, SqlBuilder.isLikeWhenPresent(sysFile.getSavedName() == null ? null : "%" + sysFile.getSavedName() + "%"))
.and(SysFileDynamicSqlSupport.originalName, SqlBuilder.isLikeWhenPresent(sysFile.getSavedName() == null ? null : "%" + sysFile.getSavedName() + "%"))
.and(SysFileDynamicSqlSupport.extension, SqlBuilder.isEqualToWhenPresent(sysFile.getExtension()))
.orderBy(SysFileDynamicSqlSupport.createTime.descending())
.build()
.render(RenderingStrategies.MYBATIS3);
return sysFileMapper.selectMany(provider);
} else {
//全部查询
return sysFileMapper.select(SelectDSLCompleter.allRows());
return sysFileMapper.select(SelectDSLCompleter.allRowsOrderedBy(SysFileDynamicSqlSupport.createTime.descending()));
}
}
@@ -94,12 +100,9 @@ public class SysFileCRUDServiceImpl implements ISysFileCRUDService {
*/
@Transactional
@Override
public int deleteSysFileByFileIds(String[] fileIds) {
DeleteStatementProvider provider = SqlBuilder.deleteFrom(SysFileDynamicSqlSupport.sysFile)
.where(SysFileDynamicSqlSupport.fileId, SqlBuilder.isIn(fileIds))
.build()
.render(RenderingStrategies.MYBATIS3);
return sysFileMapper.delete(provider);
public int deleteSysFileByFileIds(String[] fileIds) throws Exception {
FileResult result = sysFileService.deleteFiles(fileIds);
return result.getCount();
}
/**
@@ -110,7 +113,8 @@ public class SysFileCRUDServiceImpl implements ISysFileCRUDService {
*/
@Transactional
@Override
public int deleteSysFileByFileId(String fileId) {
return sysFileMapper.deleteByPrimaryKey(fileId);
public int deleteSysFileByFileId(String fileId) throws Exception {
String[] fileIds = {fileId};
return deleteSysFileByFileIds(fileIds);
}
}