前言
前端进行文件大小分割 ,按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: tempisDelTempFile: true
controller
package com.shan.controller;import com.shan.service.UploaderService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;/*** 分片上传* 思想* 1. 先 checkUpload() 文件上传前校验 根据自己公司需求校验*2. checkChunk() 检测指定分片是否存在 否 走uploadChunk()分片上传方法 是走merge()合成分片* 3. 分片上传时,会生成临时文件 必成分片是会把临时文件合成上传的真正文件,并删除临时文件**/
@RestController
@RequestMapping("uploader")
public class TestUploader {@Autowiredprivate UploaderService uploaderService;/*** 文件上传前校验** @param fileName 文件名称* @param size 文件大小 byte字节长度* @return*/@PostMapping("/checkUpload")public String checkUpload(String fileName, String size) {//根据公司自己业务 做校验 如文件名是否喊特殊字符 是否为空 等return "SUCCESS";}/*** 检查指定分片是否存在** @param md5Value 文件MD5值* @param chunk 第几片* @param moduleName 上传文件所在模块名称* @param fileTypeKey 文件类别 公司自己业务需求 会根据 模块名称+文件类别 定义上传目录* @return*/@PostMapping("/checkChunk")public Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey) {Boolean bool = uploaderService.checkChunk(md5Value, chunk, moduleName, fileTypeKey);return bool;}/*** 分片上传** @param file 文件对象* @param md5Value 文件MD5值* @param chunk 第几片* @param moduleName 上传文件所在模块名称* @param fileTypeKey 文件类别* @return*/@PostMapping("/uploadChunk")public String uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey) {System.out.println("------------开始上传:" + file.getOriginalFilename());Boolean bool = uploaderService.uploadChunk(file, md5Value, chunk, moduleName, fileTypeKey);if (!bool) {return "FAILRE";}return "SUCCESS";}/*** 合成分片** @param chunkCount 总片数* @param md5Value 文件MD5值* @param fileName 文件名称* @param moduleName 上传文件所在模块名称* @param fileTypeKey 文件类别* @return*/@PostMapping("/merge")public String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey) {String fileId = uploaderService.merge(chunkCount, md5Value, fileName, moduleName, fileTypeKey);if (StringUtils.isBlank(fileId)) {return "FAILRE";}return "SUCCESS";}}
service
package com.shan.service;import org.springframework.web.multipart.MultipartFile;public interface UploaderService {Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey);Boolean uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey);String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey);String specifiedDirectory(String fileTypeKey);}
package com.shan.service.impl;import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.shan.entity.po.CloudFile;
import com.shan.file.ResumeUploader;
import com.shan.service.UploaderService;
import com.shan.utils.ConstantUtils;
import com.shan.utils.Md5Util;
import com.shan.utils.UUIDGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.util.Date;
import java.util.Map;@Service
public class UploaderServiceImpl implements UploaderService {@Value("${spring.uploader.rootdir}")private String fileUploadPath;@Autowiredprivate ResumeUploader fileOperation;@Overridepublic Boolean checkChunk(String md5Value, Integer chunk, String moduleName, String fileTypeKey) {String path = specifiedDirectory(fileTypeKey) + moduleName + File.separator + fileTypeKey + File.separator;return fileOperation.checkChunk(path, md5Value, chunk);}@Overridepublic Boolean uploadChunk(MultipartFile file, String md5Value, Integer chunk, String moduleName, String fileTypeKey) {String path = specifiedDirectory(fileTypeKey) + moduleName + File.separator + fileTypeKey + File.separator;return fileOperation.upload(file, path, md5Value, chunk);}@Overridepublic String merge(Integer chunkCount, String md5Value, String fileName, String moduleName, String fileTypeKey) {String path = specifiedDirectory(fileTypeKey) + moduleName + File.separator + fileTypeKey + File.separator;// 目录下如果存在相同名称的文件,对文件名称做修改 xxx(1).txt xxx(2).txtfileName = this.verifyRepeatFile(path, fileName, 0);Boolean merge = fileOperation.merge(path, path, md5Value, chunkCount, fileName);if (merge) {String filePath = path + fileName;CloudFile cloudFile = new CloudFile();cloudFile.setId(UUIDGenerator.getUUID());cloudFile.setMd5(Md5Util.fastMD5(new File(filePath)));cloudFile.setName(fileName.substring(0, fileName.lastIndexOf(".")));cloudFile.setType(fileName.substring(fileName.lastIndexOf(".")));cloudFile.setPath(filePath);cloudFile.setFileSize(new File(filePath).length());cloudFile.setGmtCreate(new Date());//存数据库// int save = cloudFileMapper.save(cloudFile);int save =1;if (save > 0) {return cloudFile.getId();}}return null;}/*** 根据文件类型指定文件目录** @param fileTypeKey 文件类型*/@Overridepublic String specifiedDirectory(String fileTypeKey) {// 一、通用管理文件根路径String fPath = fileUploadPath;return fPath.endsWith("/") ? fPath : fPath + "/";}private String verifyRepeatFile(String path, String fileName, int i) {String name = fileName.substring(0, fileName.lastIndexOf("."));String suffix = fileName.substring(fileName.lastIndexOf("."));String tempFileName;if (i != 0) {tempFileName = String.format("%s%s%d%s", name, "(", i, ")");} else {tempFileName = name;}File file = new File(path + tempFileName + suffix);if (file.exists()) {return verifyRepeatFile(path, name + suffix, ++i);}return tempFileName + suffix;}}
工具类 上传相关封装
ResumeUploader、CommonUploader、UploaderUtils 、UploaderUtils
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.shan.file;import java.io.InputStream;
import java.util.List;import com.shan.entity.bean.FileInfo;
import org.springframework.web.multipart.MultipartFile;public interface ResumeUploader {Boolean checkChunk(String var1, String var2, Integer var3);Boolean compress(List<String> var1, String var2);Boolean copy(String var1, String var2);Boolean delete(String var1);InputStream download(String var1);Boolean exists(String var1);Long getDiskSize(String var1);List<FileInfo> listFiles(String var1, boolean var2);Boolean merge(String var1, String var2, String var3, Integer var4, String var5);Boolean mkDir(String var1);Boolean move(String var1, String var2);Boolean rename(String var1, String var2);Boolean upload(MultipartFile var1, String var2, String var3, Integer var4);
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.shan.file;import com.google.common.collect.Lists;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;import com.shan.entity.bean.FileInfo;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
@Component
public class CommonUploader implements ResumeUploader {@Value("${spring.uploader.tempdir}")private String tempDir;@Value("${spring.uploader.isDelTempFile}")private Boolean isDelTempFile;public Boolean checkChunk(String sharePath, String md5File, Integer chunk) {Boolean isExisted = false;String filePath = String.format("%s/%s/%s/%s.tmp", sharePath, this.tempDir, md5File, chunk);File file = new File(filePath);if (file.exists()) {isExisted = true;}return isExisted;}public Boolean compress(List<String> inputFilename, String zipFilename) {Boolean result = false;try {this.mkDir(zipFilename.substring(0, zipFilename.lastIndexOf("/") + 1));ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFilename));try {String item;String base;for(Iterator var5 = inputFilename.iterator(); var5.hasNext(); this.zip(out, item, base)) {item = (String)var5.next();base = "";String[] items = item.split("/");if (item.lastIndexOf("/") + 1 == item.length()) {base = items[items.length - 1] + "/";} else {base = items[items.length - 1];}}result = true;} catch (Throwable var10) {try {out.close();} catch (Throwable var9) {var10.addSuppressed(var9);}throw var10;}out.close();} catch (Exception var11) {var11.printStackTrace();result = false;}return result;}public Boolean copy(String fromPath, String tofilePath) {Boolean result = false;try {File fromFile = new File(fromPath);File toFile = new File(tofilePath);if (fromFile.exists()) {if (fromFile.isDirectory()) {FileUtils.copyDirectory(fromFile, toFile);} else {FileUtils.copyFile(fromFile, toFile);}result = toFile.exists();}} catch (Exception var6) {var6.printStackTrace();result = false;}return result;}public Boolean delete(String path) {Boolean result = false;try {File remoteFile = new File(path);if (!remoteFile.exists()) {return false;}if (remoteFile.isFile()) {result = remoteFile.delete();} else {FileUtils.deleteDirectory(remoteFile);result = true;}} catch (Exception var4) {var4.printStackTrace();result = false;}return result;}public InputStream download(String fromPath) {FileInputStream inputStream = null;try {File file = new File(fromPath);if (file.exists()) {inputStream = new FileInputStream(file);}} catch (Exception var4) {var4.printStackTrace();}return inputStream;}public Boolean exists(String path) {return (new File(path)).exists();}public Long getDiskSize(String path) {return this.getDiskSizeByte(path) / 1024L;}private Long getDiskSizeByte(String path) {long result = 0L;try {File file = new File(path);if (file.isFile()) {result += file.length();} else {File[] files = file.listFiles();File[] var6 = files;int var7 = files.length;for(int var8 = 0; var8 < var7; ++var8) {File f = var6[var8];if (f.isFile()) {result += f.length();}if (f.isDirectory()) {result += this.getDiskSizeByte(f.getPath().substring(f.getPath().indexOf("@") + 1));}}}} catch (Exception var10) {var10.printStackTrace();return 0L;}return result;}public List<FileInfo> listFiles(String path, boolean calculateFolderSize) {ArrayList result = Lists.newArrayList();try {File file = new File(path);if (file.exists() && file.isDirectory()) {File[] files = file.listFiles();File[] var6 = files;int var7 = files.length;for(int var8 = 0; var8 < var7; ++var8) {File f = var6[var8];Boolean isFile = f.isFile();String filePath = f.getPath();String fileName = isFile ? f.getName() : "";Long size = 0L;if (isFile) {size = f.length() / 1024L;} else if (calculateFolderSize) {size = this.getDiskSize(filePath.substring(filePath.indexOf("@") + 1));}result.add(new FileInfo(f.getName(), isFile, f.getPath(), fileName.substring(fileName.lastIndexOf(".") + 1), size));}}} catch (Exception var14) {var14.printStackTrace();}return result;}public Boolean merge(String uploadPath, String temPath, String md5File, Integer chunks, String name) {Boolean result = false;this.mkDir(uploadPath);this.mkDir(temPath);try {FileOutputStream fileOutputStream = new FileOutputStream(String.format("%s/%s", uploadPath, name));try {byte[] buf = new byte[104857600];long i = 0L;while(true) {if (i >= (long)chunks) {if (this.isDelTempFile) {this.delete(String.format("%s/%s/%s/", temPath, this.tempDir, md5File));}result = true;break;}File file = new File(String.format("%s/%s/%s/%s.tmp", temPath, this.tempDir, md5File, i));FileInputStream inputStream = new FileInputStream(file);try {boolean var13 = false;int len;while((len = inputStream.read(buf)) != -1) {fileOutputStream.write(buf, 0, len);}} catch (Throwable var17) {try {inputStream.close();} catch (Throwable var16) {var17.addSuppressed(var16);}throw var17;}inputStream.close();++i;}} catch (Throwable var18) {try {fileOutputStream.close();} catch (Throwable var15) {var18.addSuppressed(var15);}throw var18;}fileOutputStream.close();} catch (Exception var19) {result = false;}return result;}public Boolean mkDir(String path) {Boolean result = false;try {File file = new File(path);if (!file.exists()) {result = file.mkdirs();}} catch (Exception var4) {var4.printStackTrace();result = false;}return result;}public Boolean move(String fromPath, String toPath) {Boolean result = false;try {Boolean isCopy = this.copy(fromPath, toPath);Boolean isDel = false;if (isCopy) {isDel = this.delete(fromPath);}result = isCopy && isDel;} catch (Exception var6) {var6.printStackTrace();result = false;}return result;}public Boolean rename(String oldName, String newName) {Boolean result = false;try {File oldFile = new File(oldName);File newFile = new File(newName);oldFile.renameTo(newFile);result = newFile.exists();} catch (Exception var6) {var6.printStackTrace();result = false;}return result;}public Boolean upload(MultipartFile file, String sharePath, String md5File, Integer chunk) {try {String path = String.format("%s/%s/%s/", sharePath, this.tempDir, md5File);FileUtils.forceMkdir(new File(path));String chunkName = chunk == null ? "0.tmp" : chunk.toString().concat(".tmp");File savefile = new File(path.concat(chunkName));if (!savefile.exists()) {savefile.createNewFile();}file.transferTo(savefile);} catch (IOException var8) {return false;}return true;}private void zip(ZipOutputStream out, String inputFilename, String base) throws Exception {File file = new File(inputFilename);if (file.exists()) {if (file.isDirectory()) {File[] files = file.listFiles();base = base.length() == 0 ? "" : base;for(int i = 0; i < files.length; ++i) {String filePath = files[i].getPath();this.zip(out, filePath.substring(filePath.indexOf("@") + 1), base + files[i].getName());}} else {out.putNextEntry(new ZipEntry(base));int len = 0;byte[] buf = new byte[104857600];FileInputStream inputStream = new FileInputStream(file);try {while((len = inputStream.read(buf)) != -1) {out.write(buf, 0, len);}} catch (Throwable var11) {try {inputStream.close();} catch (Throwable var10) {var11.addSuppressed(var10);}throw var11;}inputStream.close();}}}public String getTempDir() {return this.tempDir;}public Boolean getIsDelTempFile() {return this.isDelTempFile;}public void setTempDir(String tempDir) {this.tempDir = tempDir;}public void setIsDelTempFile(Boolean isDelTempFile) {this.isDelTempFile = isDelTempFile;}public boolean equals(Object o) {if (o == this) {return true;} else if (!(o instanceof CommonUploader)) {return false;} else {CommonUploader other = (CommonUploader)o;if (!other.canEqual(this)) {return false;} else {Object this$isDelTempFile = this.getIsDelTempFile();Object other$isDelTempFile = other.getIsDelTempFile();if (this$isDelTempFile == null) {if (other$isDelTempFile != null) {return false;}} else if (!this$isDelTempFile.equals(other$isDelTempFile)) {return false;}Object this$tempDir = this.getTempDir();Object other$tempDir = other.getTempDir();if (this$tempDir == null) {if (other$tempDir != null) {return false;}} else if (!this$tempDir.equals(other$tempDir)) {return false;}return true;}}}protected boolean canEqual(Object other) {return other instanceof CommonUploader;}public int hashCode() {int PRIME = 59;int result = 1;Object $isDelTempFile = this.getIsDelTempFile();result = result * 59 + ($isDelTempFile == null ? 43 : $isDelTempFile.hashCode());Object $tempDir = this.getTempDir();result = result * 59 + ($tempDir == null ? 43 : $tempDir.hashCode());return result;}public String toString() {return "CommonUploader(tempDir=" + this.getTempDir() + ", isDelTempFile=" + this.getIsDelTempFile() + ")";}public CommonUploader() {}public CommonUploader(String tempDir, Boolean isDelTempFile) {this.tempDir = tempDir;this.isDelTempFile = isDelTempFile;}
}
package com.shan.utils;import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;public class Md5Util {private static final char[] hexCode = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};public static String calcMD5(File file) {try (InputStream stream = Files.newInputStream(file.toPath(), StandardOpenOption.READ)) {MessageDigest digest = MessageDigest.getInstance("MD5");byte[] buf = new byte[8192];int len;while ((len = stream.read(buf)) > 0) {digest.update(buf, 0, len);}return toHexString(digest.digest());} catch (IOException | NoSuchAlgorithmException e) {e.printStackTrace();return "";}}private static String toHexString(byte[] data) {StringBuilder r = new StringBuilder(data.length * 2);for (byte b : data) {r.append(hexCode[(b >> 4) & 0xF]);r.append(hexCode[(b & 0xF)]);}return r.toString().toLowerCase();}public static String calcMd5(String s) {if (s == null || "".equals(s)) {return "";}try {byte[] strTemp = s.getBytes();MessageDigest mdTemp = MessageDigest.getInstance("MD5");mdTemp.update(strTemp);byte[] md = mdTemp.digest();int j = md.length;char[] str = new char[j * 2];int k = 0;for (byte byte0 : md) {str[k++] = hexCode[byte0 >>> 4 & 0xf];str[k++] = hexCode[byte0 & 0xf];}return new String(str);} catch (Exception e) {e.printStackTrace();return "";}}/*** Fast MD5 PLUS*/public static String fastMD5(File file) {int len = 10000;try {if(file.length() < 10000000){return com.twmacinta.util.MD5.asHex(com.twmacinta.util.MD5.getHash(file));}byte pond[] =new byte [len];RandomAccessFile raf = new RandomAccessFile(file, "r");raf.seek(file.length() - len);raf.read(pond, 0, len);return calcMd5(toHexString(pond));} catch (Exception e) {e.printStackTrace();return "";}}public static void main(String[] args) {File file = new File("D:\\软件\\360极速浏览器.zip");String s = Md5Util.fastMD5(file);System.out.println(s);}}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//package com.shan.utils;import java.io.File;
import java.io.IOException;
import java.util.Date;import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;public class UploaderUtils {private static final Logger logger = LoggerFactory.getLogger(UploaderUtils.class);public UploaderUtils() {}public static String uploadFile(MultipartFile file, String filePath) {String fileName = file.getOriginalFilename();String newFileName = DateUtils.getInstance().dateFormat(new Date(System.currentTimeMillis()));String ext = "";if (!StringUtils.isEmpty(fileName)) {ext = fileName.substring(fileName.lastIndexOf("."), fileName.length());}//目标路径+当时时间 yyyy-MM-ddString targetFilePath = filePath + File.separator + DateUtils.getInstance().dateFormat10(System.currentTimeMillis());logger.info("上传路径{}", targetFilePath);System.out.println();File targetFile = new File(targetFilePath, newFileName + ext);if (!targetFile.getParentFile().exists()) {targetFile.getParentFile().mkdirs();}try {file.transferTo(targetFile);} catch (IllegalStateException var7) {var7.printStackTrace();} catch (IOException var8) {var8.printStackTrace();}return targetFile.getPath();}
}
前端代码 先不放了 因公司保密性 参数放上了可以直接调用
测试
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. 对文件夹中的文件循环校验 /uploader/beforeUpload方法* 2. 上传文件夹 /uploader/uploadFolder方法* @param request* fileId = 在非第一级上传文件时,fileId有值-为所在文件夹的id,上传的路径为 云盘的根路径+上文件的路径* file 上传的文件夹 多个文件* names 前台分为点击上传文件夹和拖拽上传文件夹* 点击上传文件夹时,文件的名称中不包含层级关系* 拖拽上传文件夹,文件的名称中包含层级关系,names参数为拖拽上传时使用,里面包含所有文件的层级关系* 如 names: /360驱动大师目录/下载保存目录/audio_conexant_8.66.83.51_w1064.zip.mem,/360驱动大师目录/下载保存目录/audio_conexant_8.66.83.51_w1064.zip.trt* @return*/@PostMapping("uploadFolder")public Boolean uploadFolder(HttpServletRequest request) {try {MultipartHttpServletRequest params = ((MultipartHttpServletRequest) request);// 在非第一级上传文件时,fileId有值-为所在文件夹的id,上传的路径为 根路径+上文件的路径String fileId = params.getParameter("fileId");fileId = StringUtils.isBlank(fileId) ? "0" : fileId;String filePath = "0".equals(fileId) ? "" : uploaderService.getFilePathByFileId(fileId);String targetDirectoryPath = uploaderService.rootPath() + filePath;List<MultipartFile> files = params.getFiles("file");String fileParentPaths = params.getParameter("names");String[] fileParentPathArr = null;if (StringUtils.isNoneBlank(fileParentPaths)) {fileParentPathArr = fileParentPaths.split(",");}//上传人 用户名 用于给上传文件夹赋权限 实际取此处写死模拟String userName ="SHANC";for (int i = 0; files.size() > i; i++) {MultipartFile multipartFile = files.get(i);String originalFilename = "/" + multipartFile.getOriginalFilename();originalFilename = StringUtils.isNotBlank(fileParentPaths) && fileParentPathArr != null ? fileParentPathArr[i] : originalFilename;System.out.println("文件上传路径为:" + targetDirectoryPath + originalFilename);File file = new File(targetDirectoryPath + originalFilename);if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}try {multipartFile.transferTo(file);} catch (Exception e) {e.printStackTrace();}}if (StringUtils.isNoneBlank(userName)) {new Thread(() -> FileUploadUtils.chown(userName, targetDirectoryPath)).start();}} catch (Exception e) {e.printStackTrace();}return true;}
用的工具类FileUploadUtils
package com.cloud.user.util;import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.system.OsInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.DecimalFormat;@Slf4j
public class FileUploadUtils {/*** 点*/public static final String DOT = ".";/*** 直接预览的文件类型(不通过LibreOffice转换)*/public static final String PDF = "pdf";private static String transfer(MultipartFile file, File targetFile) {try {file.transferTo(targetFile);} catch (IllegalStateException | IOException e) {e.printStackTrace();}return targetFile.getPath();}private static void mkParentFile(File targetFile) {if (!targetFile.getParentFile().exists()) {targetFile.getParentFile().mkdirs();}}public static String readableFileSize(long size) {if (size <= 0) {return "0";}final String[] units = new String[]{"B", "KB", "MB", "GB", "TB"};int digitGroups = (int) (Math.log10(size) / Math.log10(1024));return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];}/*** 文件上传** @param file 文件* @param filePath 文件路径* @return 文件路径*/public static String upload(MultipartFile file, String filePath) {File targetFile = new File(filePath, file.getOriginalFilename().replaceAll(" ", ""));mkParentFile(targetFile);return transfer(file, targetFile);}/*** 处理文件上传** @param file 上传的文件* @param targetFile 目标文件* @return 上传文件目录*/public static String upload(MultipartFile file, File targetFile) {mkParentFile(targetFile);return transfer(file, targetFile);}/*** 批量删除文件或文件夹** @param filePaths 文件路径*/public static void deletes(String[] filePaths) {for (String path : filePaths) {delete(path);}}/*** 删除文件或文件夹** @param filePath 文件路径* @return 成功与否*/public static boolean delete(String filePath) {return FileUtil.del(new File(filePath));}/*** 处理文件上传** @param file 文件* @param filePath 文件路径* @param newFileName 新文件名称* @return 文件大小*/public static Long uploadFileContinue(MultipartFile file, String filePath, String newFileName) {// 记录当前文件大小,用于判断文件是否上传完成long currentFileLength = 0;try {String fileName = file.getOriginalFilename();RandomAccessFile randomAccessfile;// 获取文件的扩展名String ext = "";if (!StringUtils.isEmpty(fileName)) {ext = fileName.substring(fileName.lastIndexOf(DOT));}File newFile = new File(filePath + newFileName + ext);if (!newFile.getParentFile().exists()) {newFile.getParentFile().mkdirs();}// 存在文件if (newFile.exists()) {randomAccessfile = new RandomAccessFile(newFile, "rw");} else {// 不存在文件,根据文件标识创建文件randomAccessfile = new RandomAccessFile(filePath + newFileName + ext, "rw");}// 开始文件传输InputStream in = file.getInputStream();if (randomAccessfile.length() < file.getInputStream().available()) {randomAccessfile.seek(randomAccessfile.length());in.skip(randomAccessfile.length());byte[] b = new byte[1024];int n;while ((n = in.read(b)) != -1) {randomAccessfile.write(b, 0, n);}}currentFileLength = randomAccessfile.length();// 关闭文件closeRandomAccessFile(randomAccessfile);} catch (Exception e) {e.printStackTrace();}return currentFileLength;}/*** 关闭随机访问文件** @param randomAccessFile 随机访问的文件*/private static void closeRandomAccessFile(RandomAccessFile randomAccessFile) {if (null != randomAccessFile) {try {randomAccessFile.close();} catch (Exception e) {e.printStackTrace();}}}/*** 转换PDF文件** @param filePath 当前文件路径* @return PDF文件转换的全路径*/public static String convertToPDF(String filePath, String targetPath) {log.info("filePath:{}", filePath);log.info("targetPath:{}", targetPath);String windowsPath = "D:/apache-tomcat-8.5.64/webapps/upload/";String command = null;String pdfPath = null;if (isLinux()) {command = "/usr/bin/libreoffice6.1 --headless --invisible --convert-to pdf " + filePath + " --outdir " + targetPath;pdfPath = targetPath + "/" + changeSuffix(filePath, PDF);} else if (isWindows()) {command = "cmd /c start soffice --headless --invisible --convert-to pdf:writer_pdf_Export " + filePath + " --outdir " + windowsPath;pdfPath = windowsPath + changeSuffix(filePath, PDF);}System.out.println("pdf command: " + command);Process exec = RuntimeUtil.exec(command);try {long startTime = System.currentTimeMillis();exec.waitFor();System.out.println("等待时长:" + (System.currentTimeMillis() - startTime));} catch (InterruptedException e) {e.printStackTrace();}return pdfPath;}/*** 更改文件后缀** @param filePath 当前文件路径* @param suffix 后缀* @return 更改后的文件名*/public static String changeSuffix(String filePath, String suffix) {return getPrefix(filePath) + DOT + suffix;}/*** 判断当前OS的类型** @return boolean*/public static boolean isWindows() {return new OsInfo().isWindows();}/*** 判断当前OS的类型** @return boolean*/public static boolean isLinux() {return new OsInfo().isLinux();}/*** 根据文件名检查文件类型,忽略大小写** @param fileName 文件名,例如hutool.png* @param extNames 被检查的扩展名数组,同一文件类型可能有多种扩展名,扩展名不带“.”* @return 是否是指定扩展名的类型*/public static boolean isType(String fileName, String... extNames) {return FileNameUtil.isType(fileName, extNames);}/*** 获取文件名(包含后缀名)** @return 文件名*/public static String getName(String filePath) {return FileNameUtil.getName(filePath);}/*** 获取前缀名** @return 文件前缀名*/public static String getPrefix(String filePath) {return FileNameUtil.getPrefix(filePath);}/*** 获取后缀名(不包括 ".")** @return 文件后缀名*/public static String getSuffix(String filePath) {return FileNameUtil.getSuffix(filePath);}/*** 文件复制(不覆盖目标文件)** @param srcPath 源文件* @param destPath 目标文件*/public static File copy(String srcPath, String destPath) {return FileUtil.copy(srcPath, destPath, false);}// public static void main(String[] args) {
// copy("C:\\Users\\lenovo\\Desktop\\123","C:\\Users\\lenovo\\Desktop\\456");
// }/*** 取得OS的文件路径的分隔符(取自系统属性:<code>file.separator</code>)。** <p>* 例如:Unix为<code>"/"</code>,Windows为<code>"\\"</code>。* </p>** @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回<code>null</code>。*/public static String getFileSeparator() {return new OsInfo().getFileSeparator();}public static void downloadFile(HttpServletRequest request, HttpServletResponse response, InputStream inputStream, String fileName) {try (OutputStream os = response.getOutputStream();BufferedInputStream bis = new BufferedInputStream(inputStream);BufferedOutputStream bos = new BufferedOutputStream(os)) {// 处理下载文件名的乱码问题(根据浏览器的不同进行处理)if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) {fileName = new String(fileName.getBytes("GB2312"), "ISO-8859-1");} else {// 对文件名进行编码处理中文问题fileName = java.net.URLEncoder.encode(fileName, "UTF-8");// 处理中文文件名的问题fileName = new String(fileName.getBytes("UTF-8"), "GBK");// 处理中文文件名的问题}response.reset();response.setCharacterEncoding("UTF-8");response.setContentType("application/x-msdownload");// 不同类型的文件对应不同的MIME类型response.setHeader("Content-Disposition", "attachment;filename=" + fileName);int bytesRead = 0;byte[] buffer = new byte[4096];while ((bytesRead = bis.read(buffer)) != -1) {bos.write(buffer, 0, bytesRead);bos.flush();}} catch (Exception ex) {throw new RuntimeException(ex.getMessage());}}/*** 删除单个文件** @param sPath 被删除文件的文件名* @return 单个文件删除成功返回true,否则返回false*/public static boolean deleteFile(String sPath) {boolean flag = false;File file = new File(sPath);// 路径为文件且不为空则进行删除if (file.isFile() && file.exists()) {file.delete();flag = true;}return flag;}/*** 删除目录(文件夹)以及目录下的文件** @param path 被删除目录的文件路径* @return 目录删除成功返回true,否则返回false*/public static boolean deleteDirectory(String path) {File dirFile = new File(path);// 如果dir对应的文件不存在,或者不是一个目录,则退出if (!dirFile.exists() || !dirFile.isDirectory()) {return false;}boolean flag = true;// 删除文件夹下的所有文件(包括子目录)File[] files = dirFile.listFiles();for (int i = 0; i < files.length; i++) {if (files[i].isFile()) {// 删除子文件flag = deleteFile(files[i].getAbsolutePath());if (!flag) {break;}} else {// 删除子目录flag = deleteDirectory(files[i].getAbsolutePath());if (!flag) {break;}}}if (!flag) {return false;}if (dirFile.delete()) {// 删除当前目录return true;} else {return false;}}public static void chown(String userName, String path) {String run = RuntimeUtils.execute("id -u " + userName);String run2 = RuntimeUtils.execute("id -g " + userName);RuntimeUtils.execute("chown -R " + run + ":" + run2 + " " + path);}}
此处用Apipost模拟下