文件base64 上传

This commit is contained in:
jiang 2025-07-29 11:05:13 +08:00
parent 9cb6d60b22
commit b3b96d9937
3 changed files with 194 additions and 26 deletions

View File

@ -3,7 +3,10 @@ package com.bonus.file.controller;
import cn.hutool.core.util.ObjectUtil;
import com.bonus.common.core.constant.HttpStatus;
import com.bonus.common.core.utils.Base64Utils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.file.entity.Base64File;
import com.bonus.file.entity.Base64ToMultipartFile;
import com.bonus.file.service.ISysFileService;
import com.bonus.system.api.domain.SysFile;
import io.swagger.annotations.Api;
@ -11,16 +14,15 @@ import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.Base64;
import java.util.UUID;
/**
* 文件请求处理
@ -29,8 +31,7 @@ import java.net.URLDecoder;
*/
@RestController
@Api("服务文件存储")
public class SysFileController
{
public class SysFileController {
private static final Logger log = LoggerFactory.getLogger(SysFileController.class);
private final ISysFileService sysFileService;
@ -42,22 +43,91 @@ public class SysFileController
/**
* 单文件上传
*
* @param file 单个文件
* @return 文件信息包括文件名和文件路径
*/
@PostMapping("upload")
@ApiOperation("上传本地文件到服务器")
public AjaxResult upload(MultipartFile file)
{
try
{
public AjaxResult upload(MultipartFile file) {
try {
// 上传并返回访问地址
if (ObjectUtil.isEmpty(file)) { return AjaxResult.error("上传文件不能为空");}
if (ObjectUtil.isEmpty(file)) {
return AjaxResult.error("上传文件不能为空");
}
SysFile sysFile = sysFileService.uploadFile(file);
return AjaxResult.success(sysFile);
} catch (Exception e) {
log.error("上传文件失败", e);
return AjaxResult.error(e.getMessage());
}
catch (Exception e)
{
}
/**
* 单文件上传支持Base64格式
*
* @param base64File Base64编码的文件内容
* @param fileName 文件名可选
* @param fileType 文件类型如image/png可选
* @return 文件信息包括文件名和文件路径
*/
@PostMapping("uploadBase64")
@ApiOperation("上传Base64文件到服务器")
public AjaxResult uploadBase64(@RequestBody Base64File entity) {
try {
// 验证Base64数据是否为空
if (StringUtils.isEmpty(entity.getBase64File())) {
return AjaxResult.error("上传文件内容不能为空");
}
// 处理可能包含的data URI前缀"data:image/png;base64,"
String base64Data;
if (entity.getBase64File().startsWith("data:")) {
// 提取真正的base64内容
String[] parts = entity.getBase64File().split(",");
if (parts.length < 2) {
return AjaxResult.error("Base64格式不正确");
}
base64Data = parts[1];
// 如果没传fileType尝试从data URI中提取
if (entity.getFileType() == null && parts[0].contains(":")) {
entity.setFileType(parts[0].split(":")[1].split(";")[0]);
}
} else {
base64Data = entity.getBase64File();
}
// 解码Base64
byte[] fileBytes = Base64.getDecoder().decode(base64Data);
// 如果没传文件名生成一个随机文件名
if (StringUtils.isEmpty(entity.getFileName())) {
entity.setFileName(UUID.randomUUID().toString());
// 如果知道文件类型添加合适的扩展名
if (entity.getFileType() != null) {
String extension = "";
if (entity.getFileType().equals("image/png")) {
extension = ".png";
} else if (entity.getFileType().equals("image/jpeg")) {
extension = ".jpg";
} else if (entity.getFileType().equals("application/pdf")) {
extension = ".pdf";
}
entity.setFileName(entity.getFileName() + extension);
}
}
// 创建临时MultipartFile对象
MultipartFile multipartFile = new Base64ToMultipartFile(fileBytes, entity.getFileName(), entity.getFileType());
// 调用原有的上传逻辑
SysFile sysFile = sysFileService.uploadFile(multipartFile);
return AjaxResult.success(sysFile);
} catch (IllegalArgumentException e) {
log.error("Base64解码失败", e);
return AjaxResult.error("Base64格式不正确");
} catch (Exception e) {
log.error("上传文件失败", e);
return AjaxResult.error(e.getMessage());
}
@ -65,30 +135,33 @@ public class SysFileController
/**
* 多文件上传
*
* @param files 多个文件流
* @return 文件信息
*/
@PostMapping("/uploadFiles")
public AjaxResult uploadFile(MultipartFile[] files) {
try {
if (ObjectUtil.isEmpty(files)) { return AjaxResult.error("上传文件不能为空");}
if (ObjectUtil.isEmpty(files)) {
return AjaxResult.error("上传文件不能为空");
}
return AjaxResult.success(sysFileService.uploadFiles(files));
} catch (Exception e)
{
} catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}
/**
* 文件下载
* @param response 请求响应
*
* @param response 请求响应
* @param objectKey除mongodb 存fileid之外其他均存上传文件的网络路径
*/
@GetMapping("/download")
public void downloadFile(HttpServletResponse response, @RequestParam String objectKey) throws IOException {
try {
String fileUrl = Base64Utils.decodeUrl(URLDecoder.decode(objectKey));
sysFileService.downloadFile(response, fileUrl);
String fileUrl = Base64Utils.decodeUrl(URLDecoder.decode(objectKey));
sysFileService.downloadFile(response, fileUrl);
} catch (Exception e) {
log.error("downloadFile error:{}", e.getMessage());
response.setStatus(HttpStatus.ERROR);
@ -105,10 +178,11 @@ public class SysFileController
/**
* 文件删除
* 从各个存储平台删除文件
*
* @param objectKey * @param objectKey除mongodb 存fileid之外其他均存上传文件的网络路径
*/
@PostMapping("/deleteFile")
public AjaxResult deleteFile(@RequestParam("objectKey") String objectKey) {
public AjaxResult deleteFile(@RequestParam("objectKey") String objectKey) {
try {
String fileUrl = Base64Utils.decodeUrl(URLDecoder.decode(objectKey));
sysFileService.deleteFile(fileUrl);
@ -120,37 +194,38 @@ public class SysFileController
/**
* 单文件上传到指定文件夹
*
* @param file 单个文件
* @return 文件信息包括文件名和文件路径
*/
@PostMapping("uploadToFolder")
@ApiOperation("上传本地文件到服务器")
public AjaxResult upload(MultipartFile file, String folderName)
{
public AjaxResult upload(MultipartFile file, String folderName) {
return AjaxResult.success("单文件上传成功");
}
/**
* 创建文件夹
*
* @param folderPath 文件夹路径例如 "folder1/subfolder/"
* @return 文件夹网络路径
*/
@PostMapping("/createFolder")
@ApiOperation("创建文件夹")
public AjaxResult createFolder(@RequestParam("folderName") String folderPath)
{
public AjaxResult createFolder(@RequestParam("folderName") String folderPath) {
sysFileService.createFolder(folderPath);
return AjaxResult.success("创建文件夹");
}
/**
* list 指定目录下所有文件信息文件名文件大小上传时间是否目录包括子文件夹
*
* @param folderPath 要获取文件夹和文件的父文件夹路径例如 "folder1/"
* @return 文件夹网络路径
*/
@GetMapping("/listFiles")
public AjaxResult listFiles(@RequestParam("folderName") String folderPath) {
public AjaxResult listFiles(@RequestParam("folderName") String folderPath) {
return AjaxResult.success(sysFileService.getFilesAndSubfolders(folderPath));
}
@ -158,13 +233,27 @@ public class SysFileController
/**
* 文件夹删除
* 从各个存储平台删除文件
*
* @param folderPath 文件夹路径例如 "folder1/subfolder/"
* @return 文件夹网络路径
*/
@PostMapping("/deleteFolder")
public AjaxResult deleteFolder(@RequestParam("folderName") String folderPath) {
public AjaxResult deleteFolder(@RequestParam("folderName") String folderPath) {
sysFileService.deleteFolder(folderPath);
return AjaxResult.success("文件夹删除成功");
}
@PostMapping("/uploadResume")
public AjaxResult uploadResume(@RequestParam("md5") String md5, @RequestParam("chunkIndex") Integer chunkIndex, @RequestParam("file") MultipartFile file, @RequestParam("totalChunks") Integer totalChunks, @RequestParam("filename") String filename) {
try {
if (ObjectUtil.isEmpty(file)) {
return AjaxResult.error("上传文件不能为空");
}
return AjaxResult.success(sysFileService.uploadResume(md5, chunkIndex, file, totalChunks, filename));
} catch (Exception e) {
return AjaxResult.error(e.getMessage());
}
}
}

View File

@ -0,0 +1,17 @@
package com.bonus.file.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Base64File {
private String fileName;
private String base64File;
private String fileType;
}

View File

@ -0,0 +1,62 @@
package com.bonus.file.entity;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
/**
* 自定义MultipartFile实现用于包装Base64解码后的数据
*/
public class Base64ToMultipartFile implements MultipartFile {
private final byte[] content;
private final String name;
private final String contentType;
public Base64ToMultipartFile(byte[] content, String name, String contentType) {
this.content = content;
this.name = name;
this.contentType = contentType;
}
@Override
public String getName() {
return name;
}
@Override
public String getOriginalFilename() {
return name;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public boolean isEmpty() {
return content == null || 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(File dest) throws IOException, IllegalStateException {
try (FileOutputStream fos = new FileOutputStream(dest)) {
fos.write(content);
}
}
}