Commit 0737c7cb authored by daniel's avatar daniel

feat(upload): 新增上传文件校验

parent 14c3378e
...@@ -12,8 +12,7 @@ import org.springframework.web.multipart.MultipartFile; ...@@ -12,8 +12,7 @@ import org.springframework.web.multipart.MultipartFile;
import com.neusoft.www.utils.web.Result; import com.neusoft.www.utils.web.Result;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.*;
import java.util.UUID;
@RestController @RestController
@RequiredArgsConstructor @RequiredArgsConstructor
...@@ -22,6 +21,42 @@ import java.util.UUID; ...@@ -22,6 +21,42 @@ import java.util.UUID;
@Slf4j @Slf4j
public class CommonController { public class CommonController {
// 定义允许上传的文件类型及其对应的魔数
private static final Map<String, byte[]> ALLOWED_FILE_TYPES = new HashMap<>();
static {
// 图片类型
ALLOWED_FILE_TYPES.put(".jpg", new byte[]{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF});
ALLOWED_FILE_TYPES.put(".jpeg", new byte[]{(byte) 0xFF, (byte) 0xD8, (byte) 0xFF});
ALLOWED_FILE_TYPES.put(".png", new byte[]{(byte) 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A});
ALLOWED_FILE_TYPES.put(".gif", new byte[]{0x47, 0x49, 0x46, 0x38});
ALLOWED_FILE_TYPES.put(".bmp", new byte[]{0x42, 0x4D});
// 文档类型
ALLOWED_FILE_TYPES.put(".pdf", new byte[]{0x25, 0x50, 0x44, 0x46});
ALLOWED_FILE_TYPES.put(".doc", new byte[]{(byte) 0xD0, (byte) 0xCF, 0x11, (byte) 0xE0, (byte) 0xA1, (byte) 0xB1, 0x1A, (byte) 0xE1});
ALLOWED_FILE_TYPES.put(".docx", new byte[]{0x50, 0x4B, 0x03, 0x04});
ALLOWED_FILE_TYPES.put(".xls", new byte[]{(byte) 0xD0, (byte) 0xCF, 0x11, (byte) 0xE0, (byte) 0xA1, (byte) 0xB1, 0x1A, (byte) 0xE1});
ALLOWED_FILE_TYPES.put(".xlsx", new byte[]{0x50, 0x4B, 0x03, 0x04});
ALLOWED_FILE_TYPES.put(".ppt", new byte[]{(byte) 0xD0, (byte) 0xCF, 0x11, (byte) 0xE0, (byte) 0xA1, (byte) 0xB1, 0x1A,(byte) 0xE1});
ALLOWED_FILE_TYPES.put(".pptx", new byte[]{0x50, 0x4B, 0x03, 0x04});
ALLOWED_FILE_TYPES.put(".txt", new byte[]{0x75, 0x73, 0x65, 0x72, 0x20, 0x6E, 0x61, 0x6D, 0x65}); // TXT 无固定魔数,此处仅示例
// 压缩文件类型
ALLOWED_FILE_TYPES.put(".zip", new byte[]{0x50, 0x4B, 0x03, 0x04});
ALLOWED_FILE_TYPES.put(".rar", new byte[]{(byte) 0x52, (byte) 0x61, (byte) 0x72, (byte) 0x21, (byte) 0x1A, (byte) 0x07, 0x00});
ALLOWED_FILE_TYPES.put(".7z", new byte[]{0x37, 0x7A, (byte) 0xBC, (byte) 0xAF, 0x27, 0x1C});
// 音频类型
ALLOWED_FILE_TYPES.put(".mp3", new byte[]{0x49, 0x44, 0x33});
ALLOWED_FILE_TYPES.put(".wav", new byte[]{0x52, 0x49, 0x46, 0x46});
// 视频类型
ALLOWED_FILE_TYPES.put(".mp4", new byte[]{0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70});
ALLOWED_FILE_TYPES.put(".avi", new byte[]{0x52, 0x49, 0x46, 0x46});
ALLOWED_FILE_TYPES.put(".mov", new byte[]{0x00, 0x00, 0x00, 0x14, 0x66, 0x74, 0x79, 0x70});
}
final private AliOssUtil aliOssUtil; final private AliOssUtil aliOssUtil;
@PostMapping("/upload") @PostMapping("/upload")
...@@ -38,7 +73,15 @@ public class CommonController { ...@@ -38,7 +73,15 @@ public class CommonController {
// 如果没有后缀名,直接返回报错信息 // 如果没有后缀名,直接返回报错信息
return Result.fail().setMsg("上传的文件没有后缀名,请检查文件"); return Result.fail().setMsg("上传的文件没有后缀名,请检查文件");
} }
String extension = originalFilename.substring(lastIndex); String extension = originalFilename.substring(lastIndex).toLowerCase();
// 检查文件扩展名是否允许
if (!ALLOWED_FILE_TYPES.containsKey(extension)) {
return Result.fail().setMsg("不允许上传该文件类型,请检查文件");
}
// 检查文件魔数
if (!checkFileMagicNumber(file.getBytes(), extension)) {
return Result.fail().setMsg("文件类型与扩展名不符,请检查文件");
}
String objectName = UUID.randomUUID() + extension; String objectName = UUID.randomUUID() + extension;
if (!Objects.equals(folder, "")) { if (!Objects.equals(folder, "")) {
objectName = folder + "/" +cmptId+ "/" + objectName; objectName = folder + "/" +cmptId+ "/" + objectName;
...@@ -52,6 +95,21 @@ public class CommonController { ...@@ -52,6 +95,21 @@ public class CommonController {
return Result.fail().setMsg("文件上传失败"); return Result.fail().setMsg("文件上传失败");
} }
/**
* 检查文件的魔数是否与扩展名匹配
* @param fileBytes 文件字节数组
* @param extension 文件扩展名
* @return 如果匹配返回 true,否则返回 false
*/
private boolean checkFileMagicNumber(byte[] fileBytes, String extension) {
byte[] expectedMagicNumber = ALLOWED_FILE_TYPES.get(extension);
if (expectedMagicNumber == null) {
return false;
}
byte[] actualMagicNumber = Arrays.copyOf(fileBytes, expectedMagicNumber.length);
return Arrays.equals(actualMagicNumber, expectedMagicNumber);
}
@PostMapping("/deleteFile") @PostMapping("/deleteFile")
@ApiOperation(value = "文件删除") @ApiOperation(value = "文件删除")
public Result<?> deleteFile(@RequestParam String url){ public Result<?> deleteFile(@RequestParam String url){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment