package com.ard.inspection.service.impl; import com.ard.inspection.service.IBigFileUploadService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.util.*; import java.util.stream.Collectors; /** * @author xia */ @Service @Slf4j public class BigFileUploadServiceImpl implements IBigFileUploadService { @Override public Map checkChunk(String fileMd5,String chunkPath) { Map result = new HashMap<>(); try { File chunkFolder = new File(chunkPath + File.separator + fileMd5); if (!chunkFolder.exists()) { result.put("exception", "分片不存在!!!"); return result; } File[] chunks = chunkFolder.listFiles(); if (chunks == null || chunks.length == 0) { result.put("exception", "无分片!!!"); return result; } List uploadedChunks = Arrays.stream(chunks) .map(file -> Integer.parseInt(file.getName().split("\\.")[0])) .collect(Collectors.toList()); result.put("message", uploadedChunks); return result; } catch (Exception e) { log.error("检查分片失败", e); result.put("exception", "检查分片失败!!!"); return result; } } @Override public Map uploadChunk(MultipartFile file, Integer chunkNumber, String fileMd5, String chunkPath) { Map result = new HashMap<>(); try { // 验证参数 if (file.isEmpty()) { result.put("exception", "文件不能为空!!!"); return result; } // 创建分片目录 String chunkDirPath = chunkPath + File.separator + fileMd5; File chunkDir = new File(chunkDirPath); if (!chunkDir.exists()) { chunkDir.mkdirs(); } // 保存分片 String chunkFileName = chunkNumber + ".part"; File chunkFile = new File(chunkDir, chunkFileName); file.transferTo(chunkFile); result.put("message", "分片上传成功!!!"); return result; } catch (IOException e) { log.error("分片上传失败", e); result.put("exception", "分片上传失败!!!"); return result; } } @Override public Map mergeChunks(String md5,String fileName,String uploadPath) { Map result = new HashMap<>(); // 临时目录 String chunkDir = uploadPath + File.separator + md5; File dir = new File(chunkDir); if (!dir.exists()) { result.put("exception", "切片目录不存在"); return result; } // 获取所有切片文件 File[] chunks = dir.listFiles(); if (chunks == null || chunks.length == 0) { result.put("exception", "没有切片文件"); return result; } // 按照切片索引排序 Arrays.sort(chunks, (a, b) -> { int aIndex = Integer.parseInt(a.getName().split("\\.")[0]); int bIndex = Integer.parseInt(b.getName().split("\\.")[0]); return aIndex - bIndex; }); // 合并后的文件,这里使用原始文件名,为了避免重名,可以加上时间戳或使用UUID // 这里根据业务需求,可以保存到数据库,记录文件路径等信息 String ext = fileName.substring(fileName.lastIndexOf(".")); String newFileName = UUID.randomUUID().toString().replace("-", "") + ext; // 生成新文件名 File mergeFile = new File(uploadPath, newFileName); try (RandomAccessFile randomAccessFile = new RandomAccessFile(mergeFile, "rw")) { byte[] buffer = new byte[1024 * 1024]; // 1MB缓冲区 for (File chunk : chunks) { try (RandomAccessFile chunkFile = new RandomAccessFile(chunk, "r")) { int len; while ((len = chunkFile.read(buffer)) != -1) { randomAccessFile.write(buffer, 0, len); } } // 删除切片文件 chunk.delete(); } // 删除临时目录 dir.delete(); } catch (IOException e) { log.error("合并文件失败", e); result.put("exception", "合并文件失败"); return result; } // 这里可以保存文件信息到数据库,例如文件路径、文件名、md5等 // fileService.saveFileInfo(...); result.put("message", "文件合并成功"); return result; } }