java本地(windows)版本分片上传
方法,controller,直接调用方法,不用实现类
但是没有实现到linux上面,因为后面用了minio去实现
/**
* 上传文件分片
* @param file 分片文件
* @param chunkIndex 分片索引
* @param totalChunks 总分片数
* @param identifier 文件唯一标识
**/
@PostMapping("/uploadChunk") public R<String> uploadChunk(@RequestParam("file") MultipartFile file, @RequestParam("chunkIndex") int chunkIndex, @RequestParam("totalChunks") int totalChunks, @RequestParam("identifier") String identifier) { try { // 生成分片存储目录 String chunkDirPath = UPLOAD_DIR + identifier; File chunkDir = new File(chunkDirPath); if (!chunkDir.exists()) { chunkDir.mkdirs(); } // 存储分片 File chunkFile = new File(chunkDir, chunkIndex + ".part"); file.transferTo(chunkFile); return R.ok("分片 " + chunkIndex + " 上传成功"); } catch (IOException e) { return R.fail("分片上传失败"); } } @PostMapping("/mergeChunks") public R<SysFile> mergeChunks(@RequestParam("identifier") String identifier, @RequestParam("fileName") String fileName) { String chunkDirPath = UPLOAD_DIR + identifier; File chunkDir = new File(chunkDirPath); if (!chunkDir.exists()) { return R.fail("分片目录不存在"); } File mergedFile = new File(UPLOAD_DIR, fileName); try (FileOutputStream fos = new FileOutputStream(mergedFile, true); FileChannel mergedChannel = fos.getChannel()) { int index = 0; while (true) { File chunkFile = new File(chunkDir, index + ".part"); if (!chunkFile.exists()) { break; } try (FileInputStream fis = new FileInputStream(chunkFile); FileChannel chunkChannel = fis.getChannel()) { mergedChannel.transferFrom(chunkChannel, mergedChannel.size(), chunkChannel.size()); } // 合并后删除分片 chunkFile.delete(); index++; } // 清理分片目录 chunkDir.delete(); SysFile sysFile = new SysFile(); sysFile.setName(fileName); // 假设文件存储到 /uploads 目录 sysFile.setUrl("G:/filetest/test/two" + fileName); return R.ok(sysFile); } catch (IOException e) { return R.fail("文件合并失败"); } }
前端核心代码
const CHUNK_SIZE = 5 * 1024 * 1024 // 1MB const handleFileChange = async (file, fileList, jd) => { filetype.value = jd uploading.value = true // 开始上传 uploadPercentage.value = 0 // 重置进度 const chunks = createChunks(file.raw) const identifier = generateIdentifier(file.raw) const totalChunks = chunks.length let uploadedChunks = 0 for (let i = 0; i < chunks.length; i++) { const formData = new FormData() formData.append('file', chunks[i]) formData.append('chunkIndex', i) formData.append('totalChunks', chunks.length) formData.append('identifier', identifier) await uploadChunk(formData) // 上传分片 uploadedChunks++ // 增加已上传分片计数 uploadPercentage.value = Math.round((uploadedChunks / totalChunks) * 100) } await mergeChunks(identifier, file.raw.name, jd) uploading.value = false // 上传完成 } const createChunks = (file) => { const chunks = [] let start = 0 while (start < file.size) { const chunk = file.slice(start, start + CHUNK_SIZE) chunks.push(chunk) start += CHUNK_SIZE } return chunks } const generateIdentifier = (file) => { return `${file.name}-${file.size}-${file.lastModified}` } const uploadChunk = async (formData, onProgress) => { try { await uploadChunks(formData) } catch (error) { console.error('Error uploading chunk:', error) throw error } } const mergeChunks = async (identifier, fileName, jd) => { try { const { code, msg } = await mergeChunk({ identifier, fileName }) if (code === 200) { uploading.value = false // 上传完成 const msgArray = JSON.parse(msg) // 如果 jd 不是 1、3、5、7、9,则添加 zdm 属性 if (![1, 3, 5, 7, 9].includes(jd)) { msgArray.zdm = jd } // 使用对象映射动态选择 fileList const fileListMap = { 1: fileList.value, 3: fileList.value, 5: fileList.value, 7: fileList.value, 9: fileList.value, two_xmjs: xmjsfileList.value, two_smxm: smxmfileList.value, two_xxhxm: xxhxmfileList.value, two_hyyjsycl: hyyjsyclfileList.value, four_cgwj: cgwjfileList.value, four_cgyxgs: cgyxgsfileList.value, four_sbcgjhzl: sbcgjhzlfileList.value, four_zfcgdlwj: zfcgdlwjfileList.value, four_zbwj: zbwjfileList.value, six_sszlcns: sszlcnsfileList.value, six_cghyjl: cghyjlfileList.value, six_xywj: xywjfileList.value, six_bxwj: bxwjfileList.value, six_pbjggs: pbjggsfileList.value, six_cjtzs: cjtzsfileList.value, six_dqht: dqhtfileList.value, eight_jssj: jssjfileList.value, eight_xmhtjbcxy: xmhtjbcxyfileList.value, eight_jlht: jlhtfileList.value, eight_sjbgs: sjbgsfileList.value, eight_bgqzd: bgqzdfileList.value, eight_sgfa: sgfafileList.value, eight_jlbg: jlbgfileList.value, eight_hwxtyjqd: hwxtyjqdfileList.value, eight_qtxtgcxwj: qtxmgcxwjfileList.value, eight_jgbk: jgbkfileList.value, eight_ysyj: ysyjfileList.value, eight_jgjss: jgjssfileList.value, eight_qtyszl: qtyszlfileList.value, nine_xmzgzl: xmzgzlfileList.value, nine_xmzgbg: xmzgbgfileList.value, } // 获取对应的 fileList const targetFileList = fileListMap[jd] if (targetFileList) { targetFileList.push(msgArray) } else { console.warn(`Unknown jd value: ${jd}`) } } } catch (error) { console.error('Error merging chunks:', error) } }