当前位置:   article > 正文

大文件分片上传_大压缩包分片上传

大压缩包分片上传

前言

前端进行文件大小分割  ,按10M分割进行分片上传,使用的项目还是前面文档介绍的poi同一个项目

另一篇poi导出文章,使用的同一个项目

poi的使用和工具类(一)

 开发

1、maven依赖

<!--文件分片上传使用到依赖 start  -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>16.0.1</version>
</dependency>
<dependency>
    <groupId>com.twmacinta</groupId>
    <artifactId>fast-md5</artifactId>
    <version>2.7.1</version>
</dependency>

<!--文件分片上传使用到依赖 end  -->

配置文件

server:
  port: 9001

#  rootdir文件上传根路径  linux:/xxx/xx/ window D:\Download\
#  tempdir: 分片临时目录
#  isDelTempFile   和片后是否删除临时目录
spring:
  uploader:
    rootdir: D:\Download\
    tempdir: temp
    isDelTempFile: true

 controller

  1. package com.shan.controller;
  2. import com.shan.service.UploaderService;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.PostMapping;
  6. import org.springframework.web.bind.annotation.RequestMapping;
  7. import org.springframework.web.bind.annotation.RestController;
  8. import org.springframework.web.multipart.MultipartFile;
  9. /**
  10. * 分片上传
  11. * 思想
  12. * 1. 先 checkUpload() 文件上传前校验 根据自己公司需求校验
  13. *2. checkChunk() 检测指定分片是否存在 否 走uploadChunk()分片上传方法 是走merge()合成分片
  14. * 3. 分片上传时,会生成临时文件 必成分片是会把临时文件合成上传的真正文件,并删除临时文件
  15. *
  16. */
  17. @RestController
  18. @RequestMapping("uploader")
  19. public class TestUploader {
  20. @Autowired
  21. private UploaderService uploaderService;
  22. /**
  23. * 文件上传前校验
  24. *
  25. * @param fileName 文件名称
  26. * @param size 文件大小 byte字节长度
  27. * @return
  28. */
  29. @PostMapping("/checkUpload")
  30. public String checkUpload(String fileName, String size) {
  31. //根据公司自己业务 做校验 如文件名是否喊特殊字符 是否为空 等
  32. return "SUCCESS";
  33. }
  34. /**
  35. * 检查指定分片是否存在
  36. *
  37. * @param md5Value 文件MD5值
  38. * @param chunk 第几片
  39. * @param moduleName 上传文件所在模块名称
  40. * @param fileTypeKey 文件类别 公司自己业务需求 会根据 模块名称+文件类别 定义上传目录
  41. * @return
  42. */
  43. @PostMapping("/checkChunk")
  44. public Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey) {
  45. Boolean bool = uploaderService.checkChunk(md5Value, chunk, moduleName, fileTypeKey);
  46. return bool;
  47. }
  48. /**
  49. * 分片上传
  50. *
  51. * @param file 文件对象
  52. * @param md5Value 文件MD5值
  53. * @param chunk 第几片
  54. * @param moduleName 上传文件所在模块名称
  55. * @param fileTypeKey 文件类别
  56. * @return
  57. */
  58. @PostMapping("/uploadChunk")
  59. public String uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey) {
  60. System.out.println("------------开始上传:" + file.getOriginalFilename());
  61. Boolean bool = uploaderService.uploadChunk(file, md5Value, chunk, moduleName, fileTypeKey);
  62. if (!bool) {
  63. return "FAILRE";
  64. }
  65. return "SUCCESS";
  66. }
  67. /**
  68. * 合成分片
  69. *
  70. * @param chunkCount 总片数
  71. * @param md5Value 文件MD5值
  72. * @param fileName 文件名称
  73. * @param moduleName 上传文件所在模块名称
  74. * @param fileTypeKey 文件类别
  75. * @return
  76. */
  77. @PostMapping("/merge")
  78. public String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey) {
  79. String fileId = uploaderService.merge(chunkCount, md5Value, fileName, moduleName, fileTypeKey);
  80. if (StringUtils.isBlank(fileId)) {
  81. return "FAILRE";
  82. }
  83. return "SUCCESS";
  84. }
  85. }

service

  1. package com.shan.service;
  2. import org.springframework.web.multipart.MultipartFile;
  3. public interface UploaderService {
  4. Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey);
  5. Boolean uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey);
  6. String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey);
  7. String specifiedDirectory(String fileTypeKey);
  8. }
  1. package com.shan.service.impl;
  2. import com.fasterxml.jackson.annotation.ObjectIdGenerators;
  3. import com.shan.entity.po.CloudFile;
  4. import com.shan.file.ResumeUploader;
  5. import com.shan.service.UploaderService;
  6. import com.shan.utils.ConstantUtils;
  7. import com.shan.utils.Md5Util;
  8. import com.shan.utils.UUIDGenerator;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.beans.factory.annotation.Value;
  11. import org.springframework.stereotype.Service;
  12. import org.springframework.web.multipart.MultipartFile;
  13. import java.io.File;
  14. import java.util.Date;
  15. import java.util.Map;
  16. @Service
  17. public class UploaderServiceImpl implements UploaderService {
  18. @Value("${spring.uploader.rootdir}")
  19. private String fileUploadPath;
  20. @Autowired
  21. private ResumeUploader fileOperation;
  22. @Override
  23. public Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey) {
  24. String path = specifiedDirectory(fileTypeKey) + moduleName + File.separator + fileTypeKey + File.separator;
  25. return fileOperation.checkChunk(path, md5Value, chunk);
  26. }
  27. @Override
  28. public Boolean uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey) {
  29. String path = specifiedDirectory(fileTypeKey) + moduleName + File.separator + fileTypeKey + File.separator;
  30. return fileOperation.upload(file, path, md5Value, chunk);
  31. }
  32. @Override
  33. public String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey) {
  34. String path = specifiedDirectory(fileTypeKey) + moduleName + File.separator + fileTypeKey + File.separator;
  35. // 目录下如果存在相同名称的文件,对文件名称做修改 xxx(1).txt xxx(2).txt
  36. fileName = this.verifyRepeatFile(path, fileName, 0);
  37. Boolean merge = fileOperation.merge(path, path, md5Value, chunkCount, fileName);
  38. if (merge) {
  39. String filePath = path + fileName;
  40. CloudFile cloudFile = new CloudFile();
  41. cloudFile.setId(UUIDGenerator.getUUID());
  42. cloudFile.setMd5(Md5Util.fastMD5(new File(filePath)));
  43. cloudFile.setName(fileName.substring(0, fileName.lastIndexOf(".")));
  44. cloudFile.setType(fileName.substring(fileName.lastIndexOf(".")));
  45. cloudFile.setPath(filePath);
  46. cloudFile.setFileSize(new File(filePath).length());
  47. cloudFile.setGmtCreate(new Date());
  48. //存数据库
  49. // int save = cloudFileMapper.save(cloudFile);
  50. int save =1;
  51. if (save > 0) {
  52. return cloudFile.getId();
  53. }
  54. }
  55. return null;
  56. }
  57. /**
  58. * 根据文件类型指定文件目录
  59. *
  60. * @param fileTypeKey 文件类型
  61. */
  62. @Override
  63. public String specifiedDirectory(String fileTypeKey) {
  64. // 一、通用管理文件根路径
  65. String fPath = fileUploadPath;
  66. return fPath.endsWith("/") ? fPath : fPath + "/";
  67. }
  68. private String verifyRepeatFile(String path, String fileName, int i) {
  69. String name = fileName.substring(0, fileName.lastIndexOf("."));
  70. String suffix = fileName.substring(fileName.lastIndexOf("."));
  71. String tempFileName;
  72. if (i != 0) {
  73. tempFileName = String.format("%s%s%d%s", name, "(", i, ")");
  74. } else {
  75. tempFileName = name;
  76. }
  77. File file = new File(path + tempFileName + suffix);
  78. if (file.exists()) {
  79. return verifyRepeatFile(path, name + suffix, ++i);
  80. }
  81. return tempFileName + suffix;
  82. }
  83. }

 工具类 上传相关封装

ResumeUploader、CommonUploader、UploaderUtils 、UploaderUtils
  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.shan.file;
  6. import java.io.InputStream;
  7. import java.util.List;
  8. import com.shan.entity.bean.FileInfo;
  9. import org.springframework.web.multipart.MultipartFile;
  10. public interface ResumeUploader {
  11. Boolean checkChunk(String var1, String var2, Integer var3);
  12. Boolean compress(List<String> var1, String var2);
  13. Boolean copy(String var1, String var2);
  14. Boolean delete(String var1);
  15. InputStream download(String var1);
  16. Boolean exists(String var1);
  17. Long getDiskSize(String var1);
  18. List<FileInfo> listFiles(String var1, boolean var2);
  19. Boolean merge(String var1, String var2, String var3, Integer var4, String var5);
  20. Boolean mkDir(String var1);
  21. Boolean move(String var1, String var2);
  22. Boolean rename(String var1, String var2);
  23. Boolean upload(MultipartFile var1, String var2, String var3, Integer var4);
  24. }
  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.shan.file;
  6. import com.google.common.collect.Lists;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileOutputStream;
  10. import java.io.IOException;
  11. import java.io.InputStream;
  12. import java.util.ArrayList;
  13. import java.util.Iterator;
  14. import java.util.List;
  15. import java.util.zip.ZipEntry;
  16. import java.util.zip.ZipOutputStream;
  17. import com.shan.entity.bean.FileInfo;
  18. import org.apache.commons.io.FileUtils;
  19. import org.springframework.beans.factory.annotation.Value;
  20. import org.springframework.stereotype.Component;
  21. import org.springframework.web.multipart.MultipartFile;
  22. @Component
  23. public class CommonUploader implements ResumeUploader {
  24. @Value("${spring.uploader.tempdir}")
  25. private String tempDir;
  26. @Value("${spring.uploader.isDelTempFile}")
  27. private Boolean isDelTempFile;
  28. public Boolean checkChunk(String sharePath, String md5File, Integer chunk) {
  29. Boolean isExisted = false;
  30. String filePath = String.format("%s/%s/%s/%s.tmp", sharePath, this.tempDir, md5File, chunk);
  31. File file = new File(filePath);
  32. if (file.exists()) {
  33. isExisted = true;
  34. }
  35. return isExisted;
  36. }
  37. public Boolean compress(List<String> inputFilename, String zipFilename) {
  38. Boolean result = false;
  39. try {
  40. this.mkDir(zipFilename.substring(0, zipFilename.lastIndexOf("/") + 1));
  41. ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilename));
  42. try {
  43. String item;
  44. String base;
  45. for(Iterator var5 = inputFilename.iterator(); var5.hasNext(); this.zip(out, item, base)) {
  46. item = (String)var5.next();
  47. base = "";
  48. String[] items = item.split("/");
  49. if (item.lastIndexOf("/") + 1 == item.length()) {
  50. base = items[items.length - 1] + "/";
  51. } else {
  52. base = items[items.length - 1];
  53. }
  54. }
  55. result = true;
  56. } catch (Throwable var10) {
  57. try {
  58. out.close();
  59. } catch (Throwable var9) {
  60. var10.addSuppressed(var9);
  61. }
  62. throw var10;
  63. }
  64. out.close();
  65. } catch (Exception var11) {
  66. var11.printStackTrace();
  67. result = false;
  68. }
  69. return result;
  70. }
  71. public Boolean copy(String fromPath, String tofilePath) {
  72. Boolean result = false;
  73. try {
  74. File fromFile = new File(fromPath);
  75. File toFile = new File(tofilePath);
  76. if (fromFile.exists()) {
  77. if (fromFile.isDirectory()) {
  78. FileUtils.copyDirectory(fromFile, toFile);
  79. } else {
  80. FileUtils.copyFile(fromFile, toFile);
  81. }
  82. result = toFile.exists();
  83. }
  84. } catch (Exception var6) {
  85. var6.printStackTrace();
  86. result = false;
  87. }
  88. return result;
  89. }
  90. public Boolean delete(String path) {
  91. Boolean result = false;
  92. try {
  93. File remoteFile = new File(path);
  94. if (!remoteFile.exists()) {
  95. return false;
  96. }
  97. if (remoteFile.isFile()) {
  98. result = remoteFile.delete();
  99. } else {
  100. FileUtils.deleteDirectory(remoteFile);
  101. result = true;
  102. }
  103. } catch (Exception var4) {
  104. var4.printStackTrace();
  105. result = false;
  106. }
  107. return result;
  108. }
  109. public InputStream download(String fromPath) {
  110. FileInputStream inputStream = null;
  111. try {
  112. File file = new File(fromPath);
  113. if (file.exists()) {
  114. inputStream = new FileInputStream(file);
  115. }
  116. } catch (Exception var4) {
  117. var4.printStackTrace();
  118. }
  119. return inputStream;
  120. }
  121. public Boolean exists(String path) {
  122. return (new File(path)).exists();
  123. }
  124. public Long getDiskSize(String path) {
  125. return this.getDiskSizeByte(path) / 1024L;
  126. }
  127. private Long getDiskSizeByte(String path) {
  128. long result = 0L;
  129. try {
  130. File file = new File(path);
  131. if (file.isFile()) {
  132. result += file.length();
  133. } else {
  134. File[] files = file.listFiles();
  135. File[] var6 = files;
  136. int var7 = files.length;
  137. for(int var8 = 0; var8 < var7; ++var8) {
  138. File f = var6[var8];
  139. if (f.isFile()) {
  140. result += f.length();
  141. }
  142. if (f.isDirectory()) {
  143. result += this.getDiskSizeByte(f.getPath().substring(f.getPath().indexOf("@") + 1));
  144. }
  145. }
  146. }
  147. } catch (Exception var10) {
  148. var10.printStackTrace();
  149. return 0L;
  150. }
  151. return result;
  152. }
  153. public List<FileInfo> listFiles(String path, boolean calculateFolderSize) {
  154. ArrayList result = Lists.newArrayList();
  155. try {
  156. File file = new File(path);
  157. if (file.exists() && file.isDirectory()) {
  158. File[] files = file.listFiles();
  159. File[] var6 = files;
  160. int var7 = files.length;
  161. for(int var8 = 0; var8 < var7; ++var8) {
  162. File f = var6[var8];
  163. Boolean isFile = f.isFile();
  164. String filePath = f.getPath();
  165. String fileName = isFile ? f.getName() : "";
  166. Long size = 0L;
  167. if (isFile) {
  168. size = f.length() / 1024L;
  169. } else if (calculateFolderSize) {
  170. size = this.getDiskSize(filePath.substring(filePath.indexOf("@") + 1));
  171. }
  172. result.add(new FileInfo(f.getName(), isFile, f.getPath(), fileName.substring(fileName.lastIndexOf(".") + 1), size));
  173. }
  174. }
  175. } catch (Exception var14) {
  176. var14.printStackTrace();
  177. }
  178. return result;
  179. }
  180. public Boolean merge(String uploadPath, String temPath, String md5File, Integer chunks, String name) {
  181. Boolean result = false;
  182. this.mkDir(uploadPath);
  183. this.mkDir(temPath);
  184. try {
  185. FileOutputStream fileOutputStream = new FileOutputStream(String.format("%s/%s", uploadPath, name));
  186. try {
  187. byte[] buf = new byte[104857600];
  188. long i = 0L;
  189. while(true) {
  190. if (i >= (long)chunks) {
  191. if (this.isDelTempFile) {
  192. this.delete(String.format("%s/%s/%s/", temPath, this.tempDir, md5File));
  193. }
  194. result = true;
  195. break;
  196. }
  197. File file = new File(String.format("%s/%s/%s/%s.tmp", temPath, this.tempDir, md5File, i));
  198. FileInputStream inputStream = new FileInputStream(file);
  199. try {
  200. boolean var13 = false;
  201. int len;
  202. while((len = inputStream.read(buf)) != -1) {
  203. fileOutputStream.write(buf, 0, len);
  204. }
  205. } catch (Throwable var17) {
  206. try {
  207. inputStream.close();
  208. } catch (Throwable var16) {
  209. var17.addSuppressed(var16);
  210. }
  211. throw var17;
  212. }
  213. inputStream.close();
  214. ++i;
  215. }
  216. } catch (Throwable var18) {
  217. try {
  218. fileOutputStream.close();
  219. } catch (Throwable var15) {
  220. var18.addSuppressed(var15);
  221. }
  222. throw var18;
  223. }
  224. fileOutputStream.close();
  225. } catch (Exception var19) {
  226. result = false;
  227. }
  228. return result;
  229. }
  230. public Boolean mkDir(String path) {
  231. Boolean result = false;
  232. try {
  233. File file = new File(path);
  234. if (!file.exists()) {
  235. result = file.mkdirs();
  236. }
  237. } catch (Exception var4) {
  238. var4.printStackTrace();
  239. result = false;
  240. }
  241. return result;
  242. }
  243. public Boolean move(String fromPath, String toPath) {
  244. Boolean result = false;
  245. try {
  246. Boolean isCopy = this.copy(fromPath, toPath);
  247. Boolean isDel = false;
  248. if (isCopy) {
  249. isDel = this.delete(fromPath);
  250. }
  251. result = isCopy && isDel;
  252. } catch (Exception var6) {
  253. var6.printStackTrace();
  254. result = false;
  255. }
  256. return result;
  257. }
  258. public Boolean rename(String oldName, String newName) {
  259. Boolean result = false;
  260. try {
  261. File oldFile = new File(oldName);
  262. File newFile = new File(newName);
  263. oldFile.renameTo(newFile);
  264. result = newFile.exists();
  265. } catch (Exception var6) {
  266. var6.printStackTrace();
  267. result = false;
  268. }
  269. return result;
  270. }
  271. public Boolean upload(MultipartFile file, String sharePath, String md5File, Integer chunk) {
  272. try {
  273. String path = String.format("%s/%s/%s/", sharePath, this.tempDir, md5File);
  274. FileUtils.forceMkdir(new File(path));
  275. String chunkName = chunk == null ? "0.tmp" : chunk.toString().concat(".tmp");
  276. File savefile = new File(path.concat(chunkName));
  277. if (!savefile.exists()) {
  278. savefile.createNewFile();
  279. }
  280. file.transferTo(savefile);
  281. } catch (IOException var8) {
  282. return false;
  283. }
  284. return true;
  285. }
  286. private void zip(ZipOutputStream out, String inputFilename, String base) throws Exception {
  287. File file = new File(inputFilename);
  288. if (file.exists()) {
  289. if (file.isDirectory()) {
  290. File[] files = file.listFiles();
  291. base = base.length() == 0 ? "" : base;
  292. for(int i = 0; i < files.length; ++i) {
  293. String filePath = files[i].getPath();
  294. this.zip(out, filePath.substring(filePath.indexOf("@") + 1), base + files[i].getName());
  295. }
  296. } else {
  297. out.putNextEntry(new ZipEntry(base));
  298. int len = 0;
  299. byte[] buf = new byte[104857600];
  300. FileInputStream inputStream = new FileInputStream(file);
  301. try {
  302. while((len = inputStream.read(buf)) != -1) {
  303. out.write(buf, 0, len);
  304. }
  305. } catch (Throwable var11) {
  306. try {
  307. inputStream.close();
  308. } catch (Throwable var10) {
  309. var11.addSuppressed(var10);
  310. }
  311. throw var11;
  312. }
  313. inputStream.close();
  314. }
  315. }
  316. }
  317. public String getTempDir() {
  318. return this.tempDir;
  319. }
  320. public Boolean getIsDelTempFile() {
  321. return this.isDelTempFile;
  322. }
  323. public void setTempDir(String tempDir) {
  324. this.tempDir = tempDir;
  325. }
  326. public void setIsDelTempFile(Boolean isDelTempFile) {
  327. this.isDelTempFile = isDelTempFile;
  328. }
  329. public boolean equals(Object o) {
  330. if (o == this) {
  331. return true;
  332. } else if (!(o instanceof CommonUploader)) {
  333. return false;
  334. } else {
  335. CommonUploader other = (CommonUploader)o;
  336. if (!other.canEqual(this)) {
  337. return false;
  338. } else {
  339. Object this$isDelTempFile = this.getIsDelTempFile();
  340. Object other$isDelTempFile = other.getIsDelTempFile();
  341. if (this$isDelTempFile == null) {
  342. if (other$isDelTempFile != null) {
  343. return false;
  344. }
  345. } else if (!this$isDelTempFile.equals(other$isDelTempFile)) {
  346. return false;
  347. }
  348. Object this$tempDir = this.getTempDir();
  349. Object other$tempDir = other.getTempDir();
  350. if (this$tempDir == null) {
  351. if (other$tempDir != null) {
  352. return false;
  353. }
  354. } else if (!this$tempDir.equals(other$tempDir)) {
  355. return false;
  356. }
  357. return true;
  358. }
  359. }
  360. }
  361. protected boolean canEqual(Object other) {
  362. return other instanceof CommonUploader;
  363. }
  364. public int hashCode() {
  365. int PRIME = 59;
  366. int result = 1;
  367. Object $isDelTempFile = this.getIsDelTempFile();
  368. result = result * 59 + ($isDelTempFile == null ? 43 : $isDelTempFile.hashCode());
  369. Object $tempDir = this.getTempDir();
  370. result = result * 59 + ($tempDir == null ? 43 : $tempDir.hashCode());
  371. return result;
  372. }
  373. public String toString() {
  374. return "CommonUploader(tempDir=" + this.getTempDir() + ", isDelTempFile=" + this.getIsDelTempFile() + ")";
  375. }
  376. public CommonUploader() {
  377. }
  378. public CommonUploader(String tempDir, Boolean isDelTempFile) {
  379. this.tempDir = tempDir;
  380. this.isDelTempFile = isDelTempFile;
  381. }
  382. }
  1. package com.shan.utils;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.RandomAccessFile;
  6. import java.nio.file.Files;
  7. import java.nio.file.StandardOpenOption;
  8. import java.security.MessageDigest;
  9. import java.security.NoSuchAlgorithmException;
  10. public class Md5Util {
  11. private static final char[] hexCode = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  12. public static String calcMD5(File file) {
  13. try (InputStream stream = Files.newInputStream(file.toPath(), StandardOpenOption.READ)) {
  14. MessageDigest digest = MessageDigest.getInstance("MD5");
  15. byte[] buf = new byte[8192];
  16. int len;
  17. while ((len = stream.read(buf)) > 0) {
  18. digest.update(buf, 0, len);
  19. }
  20. return toHexString(digest.digest());
  21. } catch (IOException | NoSuchAlgorithmException e) {
  22. e.printStackTrace();
  23. return "";
  24. }
  25. }
  26. private static String toHexString(byte[] data) {
  27. StringBuilder r = new StringBuilder(data.length * 2);
  28. for (byte b : data) {
  29. r.append(hexCode[(b >> 4) & 0xF]);
  30. r.append(hexCode[(b & 0xF)]);
  31. }
  32. return r.toString().toLowerCase();
  33. }
  34. public static String calcMd5(String s) {
  35. if (s == null || "".equals(s)) {
  36. return "";
  37. }
  38. try {
  39. byte[] strTemp = s.getBytes();
  40. MessageDigest mdTemp = MessageDigest.getInstance("MD5");
  41. mdTemp.update(strTemp);
  42. byte[] md = mdTemp.digest();
  43. int j = md.length;
  44. char[] str = new char[j * 2];
  45. int k = 0;
  46. for (byte byte0 : md) {
  47. str[k++] = hexCode[byte0 >>> 4 & 0xf];
  48. str[k++] = hexCode[byte0 & 0xf];
  49. }
  50. return new String(str);
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. return "";
  54. }
  55. }
  56. /**
  57. * Fast MD5 PLUS
  58. */
  59. public static String fastMD5(File file) {
  60. int len = 10000;
  61. try {
  62. if(file.length() < 10000000){
  63. return com.twmacinta.util.MD5.asHex(com.twmacinta.util.MD5.getHash(file));
  64. }
  65. byte pond[] =new byte [len];
  66. RandomAccessFile raf = new RandomAccessFile(file, "r");
  67. raf.seek(file.length() - len);
  68. raf.read(pond, 0, len);
  69. return calcMd5(toHexString(pond));
  70. } catch (Exception e) {
  71. e.printStackTrace();
  72. return "";
  73. }
  74. }
  75. public static void main(String[] args) {
  76. File file = new File("D:\\软件\\360极速浏览器.zip");
  77. String s = Md5Util.fastMD5(file);
  78. System.out.println(s);
  79. }
  80. }

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by Fernflower decompiler)
  4. //
  5. package com.shan.utils;
  6. import java.io.File;
  7. import java.io.IOException;
  8. import java.util.Date;
  9. import org.apache.commons.lang3.StringUtils;
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import org.springframework.web.multipart.MultipartFile;
  13. public class UploaderUtils {
  14. private static final Logger logger = LoggerFactory.getLogger(UploaderUtils.class);
  15. public UploaderUtils() {
  16. }
  17. public static String uploadFile(MultipartFile file, String filePath) {
  18. String fileName = file.getOriginalFilename();
  19. String newFileName = DateUtils.getInstance().dateFormat(new Date(System.currentTimeMillis()));
  20. String ext = "";
  21. if (!StringUtils.isEmpty(fileName)) {
  22. ext = fileName.substring(fileName.lastIndexOf("."), fileName.length());
  23. }
  24. //目标路径+当时时间 yyyy-MM-dd
  25. String targetFilePath = filePath + File.separator + DateUtils.getInstance().dateFormat10(System.currentTimeMillis());
  26. logger.info("上传路径{}", targetFilePath);
  27. System.out.println();
  28. File targetFile = new File(targetFilePath, newFileName + ext);
  29. if (!targetFile.getParentFile().exists()) {
  30. targetFile.getParentFile().mkdirs();
  31. }
  32. try {
  33. file.transferTo(targetFile);
  34. } catch (IllegalStateException var7) {
  35. var7.printStackTrace();
  36. } catch (IOException var8) {
  37. var8.printStackTrace();
  38. }
  39. return targetFile.getPath();
  40. }
  41. }

前端代码 先不放了  因公司保密性  参数放上了可以直接调用

测试

1、检查分片是否存在 

chunk   0

md5Value  e80c5740b90c9366d0ab0b271f8a10c8

moduleName

fileTypeKey   3D/DCV/v1

 2、上传分片

file   选择文件

chunk   0

md5Value  e80c5740b90c9366d0ab0b271f8a10c8

moduleName

fileTypeKey   3D/DCV/v1

上传后看上传的位置   会生成分片文件

 3、合并分片

fileName  test2.xls

chunkCount   1

md5Value  e80c5740b90c9366d0ab0b271f8a10c8

moduleName

fileTypeKey   3D/DCV/v1

合并分片后会删除 临时分片文件  并生成原文件

文件夹上传

前台分为点击上传文件夹和拖拽文件夹

思路:

  * 文件夹上传 前台分为点击上传文件夹和拖拽上传文件夹
     *  1. 对文件夹中的文件循环校验  /uploader/beforeUpload方法
     *  2. 上传文件夹    /uploader/uploadFolder方法

  1. /**
  2. * 文件夹上传 前台分为点击上传文件夹和拖拽上传文件夹
  3. * 1. 对文件夹中的文件循环校验 /uploader/beforeUpload方法
  4. * 2. 上传文件夹 /uploader/uploadFolder方法
  5. * @param request
  6. * fileId = 在非第一级上传文件时,fileId有值-为所在文件夹的id,上传的路径为 云盘的根路径+上文件的路径
  7. * file 上传的文件夹 多个文件
  8. * names 前台分为点击上传文件夹和拖拽上传文件夹
  9. * 点击上传文件夹时,文件的名称中不包含层级关系
  10. * 拖拽上传文件夹,文件的名称中包含层级关系,names参数为拖拽上传时使用,里面包含所有文件的层级关系
  11. * 如 names: /360驱动大师目录/下载保存目录/audio_conexant_8.66.83.51_w1064.zip.mem,/360驱动大师目录/下载保存目录/audio_conexant_8.66.83.51_w1064.zip.trt
  12. * @return
  13. */
  14. @PostMapping("uploadFolder")
  15. public Boolean uploadFolder(HttpServletRequest request) {
  16. try {
  17. MultipartHttpServletRequest params = ((MultipartHttpServletRequest) request);
  18. // 在非第一级上传文件时,fileId有值-为所在文件夹的id,上传的路径为 根路径+上文件的路径
  19. String fileId = params.getParameter("fileId");
  20. fileId = StringUtils.isBlank(fileId) ? "0" : fileId;
  21. String filePath = "0".equals(fileId) ? "" : uploaderService.getFilePathByFileId(fileId);
  22. String targetDirectoryPath = uploaderService.rootPath() + filePath;
  23. List<MultipartFile> files = params.getFiles("file");
  24. String fileParentPaths = params.getParameter("names");
  25. String[] fileParentPathArr = null;
  26. if (StringUtils.isNoneBlank(fileParentPaths)) {
  27. fileParentPathArr = fileParentPaths.split(",");
  28. }
  29. //上传人 用户名 用于给上传文件夹赋权限 实际取此处写死模拟
  30. String userName ="SHANC";
  31. for (int i = 0; files.size() > i; i++) {
  32. MultipartFile multipartFile = files.get(i);
  33. String originalFilename = "/" + multipartFile.getOriginalFilename();
  34. originalFilename = StringUtils.isNotBlank(fileParentPaths) && fileParentPathArr != null ? fileParentPathArr[i] : originalFilename;
  35. System.out.println("文件上传路径为:" + targetDirectoryPath + originalFilename);
  36. File file = new File(targetDirectoryPath + originalFilename);
  37. if (!file.getParentFile().exists()) {
  38. file.getParentFile().mkdirs();
  39. }
  40. try {
  41. multipartFile.transferTo(file);
  42. } catch (Exception e) {
  43. e.printStackTrace();
  44. }
  45. }
  46. if (StringUtils.isNoneBlank(userName)) {
  47. new Thread(() -> FileUploadUtils.chown(userName, targetDirectoryPath)).start();
  48. }
  49. } catch (Exception e) {
  50. e.printStackTrace();
  51. }
  52. return true;
  53. }

用的工具类FileUploadUtils

  1. package com.cloud.user.util;
  2. import cn.hutool.core.io.FileUtil;
  3. import cn.hutool.core.io.file.FileNameUtil;
  4. import cn.hutool.core.util.RuntimeUtil;
  5. import cn.hutool.system.OsInfo;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.util.StringUtils;
  8. import org.springframework.web.multipart.MultipartFile;
  9. import javax.servlet.http.HttpServletRequest;
  10. import javax.servlet.http.HttpServletResponse;
  11. import java.io.*;
  12. import java.text.DecimalFormat;
  13. @Slf4j
  14. public class FileUploadUtils {
  15. /**
  16. * 点
  17. */
  18. public static final String DOT = ".";
  19. /**
  20. * 直接预览的文件类型(不通过LibreOffice转换)
  21. */
  22. public static final String PDF = "pdf";
  23. private static String transfer(MultipartFile file, File targetFile) {
  24. try {
  25. file.transferTo(targetFile);
  26. } catch (IllegalStateException | IOException e) {
  27. e.printStackTrace();
  28. }
  29. return targetFile.getPath();
  30. }
  31. private static void mkParentFile(File targetFile) {
  32. if (!targetFile.getParentFile().exists()) {
  33. targetFile.getParentFile().mkdirs();
  34. }
  35. }
  36. public static String readableFileSize(long size) {
  37. if (size <= 0) {
  38. return "0";
  39. }
  40. final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};
  41. int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
  42. return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
  43. }
  44. /**
  45. * 文件上传
  46. *
  47. * @param file 文件
  48. * @param filePath 文件路径
  49. * @return 文件路径
  50. */
  51. public static String upload(MultipartFile file, String filePath) {
  52. File targetFile = new File(filePath, file.getOriginalFilename().replaceAll(" ", ""));
  53. mkParentFile(targetFile);
  54. return transfer(file, targetFile);
  55. }
  56. /**
  57. * 处理文件上传
  58. *
  59. * @param file 上传的文件
  60. * @param targetFile 目标文件
  61. * @return 上传文件目录
  62. */
  63. public static String upload(MultipartFile file, File targetFile) {
  64. mkParentFile(targetFile);
  65. return transfer(file, targetFile);
  66. }
  67. /**
  68. * 批量删除文件或文件夹
  69. *
  70. * @param filePaths 文件路径
  71. */
  72. public static void deletes(String[] filePaths) {
  73. for (String path : filePaths) {
  74. delete(path);
  75. }
  76. }
  77. /**
  78. * 删除文件或文件夹
  79. *
  80. * @param filePath 文件路径
  81. * @return 成功与否
  82. */
  83. public static boolean delete(String filePath) {
  84. return FileUtil.del(new File(filePath));
  85. }
  86. /**
  87. * 处理文件上传
  88. *
  89. * @param file 文件
  90. * @param filePath 文件路径
  91. * @param newFileName 新文件名称
  92. * @return 文件大小
  93. */
  94. public static Long uploadFileContinue(MultipartFile file, String filePath, String newFileName) {
  95. // 记录当前文件大小,用于判断文件是否上传完成
  96. long currentFileLength = 0;
  97. try {
  98. String fileName = file.getOriginalFilename();
  99. RandomAccessFile randomAccessfile;
  100. // 获取文件的扩展名
  101. String ext = "";
  102. if (!StringUtils.isEmpty(fileName)) {
  103. ext = fileName.substring(fileName.lastIndexOf(DOT));
  104. }
  105. File newFile = new File(filePath + newFileName + ext);
  106. if (!newFile.getParentFile().exists()) {
  107. newFile.getParentFile().mkdirs();
  108. }
  109. // 存在文件
  110. if (newFile.exists()) {
  111. randomAccessfile = new RandomAccessFile(newFile, "rw");
  112. } else {
  113. // 不存在文件,根据文件标识创建文件
  114. randomAccessfile = new RandomAccessFile(filePath + newFileName + ext, "rw");
  115. }
  116. // 开始文件传输
  117. InputStream in = file.getInputStream();
  118. if (randomAccessfile.length() < file.getInputStream().available()) {
  119. randomAccessfile.seek(randomAccessfile.length());
  120. in.skip(randomAccessfile.length());
  121. byte[] b = new byte[1024];
  122. int n;
  123. while ((n = in.read(b)) != -1) {
  124. randomAccessfile.write(b, 0, n);
  125. }
  126. }
  127. currentFileLength = randomAccessfile.length();
  128. // 关闭文件
  129. closeRandomAccessFile(randomAccessfile);
  130. } catch (Exception e) {
  131. e.printStackTrace();
  132. }
  133. return currentFileLength;
  134. }
  135. /**
  136. * 关闭随机访问文件
  137. *
  138. * @param randomAccessFile 随机访问的文件
  139. */
  140. private static void closeRandomAccessFile(RandomAccessFile randomAccessFile) {
  141. if (null != randomAccessFile) {
  142. try {
  143. randomAccessFile.close();
  144. } catch (Exception e) {
  145. e.printStackTrace();
  146. }
  147. }
  148. }
  149. /**
  150. * 转换PDF文件
  151. *
  152. * @param filePath 当前文件路径
  153. * @return PDF文件转换的全路径
  154. */
  155. public static String convertToPDF(String filePath, String targetPath) {
  156. log.info("filePath:{}", filePath);
  157. log.info("targetPath:{}", targetPath);
  158. String windowsPath = "D:/apache-tomcat-8.5.64/webapps/upload/";
  159. String command = null;
  160. String pdfPath = null;
  161. if (isLinux()) {
  162. command = "/usr/bin/libreoffice6.1 --headless --invisible --convert-to pdf " + filePath + " --outdir " + targetPath;
  163. pdfPath = targetPath + "/" + changeSuffix(filePath, PDF);
  164. } else if (isWindows()) {
  165. command = "cmd /c start soffice --headless --invisible --convert-to pdf:writer_pdf_Export " + filePath + " --outdir " + windowsPath;
  166. pdfPath = windowsPath + changeSuffix(filePath, PDF);
  167. }
  168. System.out.println("pdf command: " + command);
  169. Process exec = RuntimeUtil.exec(command);
  170. try {
  171. long startTime = System.currentTimeMillis();
  172. exec.waitFor();
  173. System.out.println("等待时长:" + (System.currentTimeMillis() - startTime));
  174. } catch (InterruptedException e) {
  175. e.printStackTrace();
  176. }
  177. return pdfPath;
  178. }
  179. /**
  180. * 更改文件后缀
  181. *
  182. * @param filePath 当前文件路径
  183. * @param suffix 后缀
  184. * @return 更改后的文件名
  185. */
  186. public static String changeSuffix(String filePath, String suffix) {
  187. return getPrefix(filePath) + DOT + suffix;
  188. }
  189. /**
  190. * 判断当前OS的类型
  191. *
  192. * @return boolean
  193. */
  194. public static boolean isWindows() {
  195. return new OsInfo().isWindows();
  196. }
  197. /**
  198. * 判断当前OS的类型
  199. *
  200. * @return boolean
  201. */
  202. public static boolean isLinux() {
  203. return new OsInfo().isLinux();
  204. }
  205. /**
  206. * 根据文件名检查文件类型,忽略大小写
  207. *
  208. * @param fileName 文件名,例如hutool.png
  209. * @param extNames 被检查的扩展名数组,同一文件类型可能有多种扩展名,扩展名不带“.”
  210. * @return 是否是指定扩展名的类型
  211. */
  212. public static boolean isType(String fileName, String... extNames) {
  213. return FileNameUtil.isType(fileName, extNames);
  214. }
  215. /**
  216. * 获取文件名(包含后缀名)
  217. *
  218. * @return 文件名
  219. */
  220. public static String getName(String filePath) {
  221. return FileNameUtil.getName(filePath);
  222. }
  223. /**
  224. * 获取前缀名
  225. *
  226. * @return 文件前缀名
  227. */
  228. public static String getPrefix(String filePath) {
  229. return FileNameUtil.getPrefix(filePath);
  230. }
  231. /**
  232. * 获取后缀名(不包括 ".")
  233. *
  234. * @return 文件后缀名
  235. */
  236. public static String getSuffix(String filePath) {
  237. return FileNameUtil.getSuffix(filePath);
  238. }
  239. /**
  240. * 文件复制(不覆盖目标文件)
  241. *
  242. * @param srcPath 源文件
  243. * @param destPath 目标文件
  244. */
  245. public static File copy(String srcPath, String destPath) {
  246. return FileUtil.copy(srcPath, destPath, false);
  247. }
  248. // public static void main(String[] args) {
  249. // copy("C:\\Users\\lenovo\\Desktop\\123","C:\\Users\\lenovo\\Desktop\\456");
  250. // }
  251. /**
  252. * 取得OS的文件路径的分隔符(取自系统属性:<code>file.separator</code>)。
  253. *
  254. * <p>
  255. * 例如:Unix为<code>"/"</code>,Windows为<code>"\\"</code>。
  256. * </p>
  257. *
  258. * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回<code>null</code>。
  259. */
  260. public static String getFileSeparator() {
  261. return new OsInfo().getFileSeparator();
  262. }
  263. public static void downloadFile(HttpServletRequest request, HttpServletResponse response, InputStream inputStream, String fileName) {
  264. try (OutputStream os = response.getOutputStream();
  265. BufferedInputStream bis = new BufferedInputStream(inputStream);
  266. BufferedOutputStream bos = new BufferedOutputStream(os)) {
  267. // 处理下载文件名的乱码问题(根据浏览器的不同进行处理)
  268. if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) {
  269. fileName = new String(fileName.getBytes("GB2312"), "ISO-8859-1");
  270. } else {
  271. // 对文件名进行编码处理中文问题
  272. fileName = java.net.URLEncoder.encode(fileName, "UTF-8");// 处理中文文件名的问题
  273. fileName = new String(fileName.getBytes("UTF-8"), "GBK");// 处理中文文件名的问题
  274. }
  275. response.reset();
  276. response.setCharacterEncoding("UTF-8");
  277. response.setContentType("application/x-msdownload");// 不同类型的文件对应不同的MIME类型
  278. response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
  279. int bytesRead = 0;
  280. byte[] buffer = new byte[4096];
  281. while ((bytesRead = bis.read(buffer)) != -1) {
  282. bos.write(buffer, 0, bytesRead);
  283. bos.flush();
  284. }
  285. } catch (Exception ex) {
  286. throw new RuntimeException(ex.getMessage());
  287. }
  288. }
  289. /**
  290. * 删除单个文件
  291. *
  292. * @param sPath 被删除文件的文件名
  293. * @return 单个文件删除成功返回true,否则返回false
  294. */
  295. public static boolean deleteFile(String sPath) {
  296. boolean flag = false;
  297. File file = new File(sPath);
  298. // 路径为文件且不为空则进行删除
  299. if (file.isFile() && file.exists()) {
  300. file.delete();
  301. flag = true;
  302. }
  303. return flag;
  304. }
  305. /**
  306. * 删除目录(文件夹)以及目录下的文件
  307. *
  308. * @param path 被删除目录的文件路径
  309. * @return 目录删除成功返回true,否则返回false
  310. */
  311. public static boolean deleteDirectory(String path) {
  312. File dirFile = new File(path);
  313. // 如果dir对应的文件不存在,或者不是一个目录,则退出
  314. if (!dirFile.exists() || !dirFile.isDirectory()) {
  315. return false;
  316. }
  317. boolean flag = true;
  318. // 删除文件夹下的所有文件(包括子目录)
  319. File[] files = dirFile.listFiles();
  320. for (int i = 0; i < files.length; i++) {
  321. if (files[i].isFile()) {// 删除子文件
  322. flag = deleteFile(files[i].getAbsolutePath());
  323. if (!flag) {
  324. break;
  325. }
  326. } else {// 删除子目录
  327. flag = deleteDirectory(files[i].getAbsolutePath());
  328. if (!flag) {
  329. break;
  330. }
  331. }
  332. }
  333. if (!flag) {
  334. return false;
  335. }
  336. if (dirFile.delete()) {// 删除当前目录
  337. return true;
  338. } else {
  339. return false;
  340. }
  341. }
  342. public static void chown(String userName, String path) {
  343. String run = RuntimeUtils.execute("id -u " + userName);
  344. String run2 = RuntimeUtils.execute("id -g " + userName);
  345. RuntimeUtils.execute("chown -R " + run + ":" + run2 + " " + path);
  346. }
  347. }

此处用Apipost模拟下

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/871572
推荐阅读
相关标签
  

闽ICP备14008679号