package cc.mrbird.febs.common.utils; import cc.mrbird.febs.common.entity.FebsConstant; import cn.hutool.core.lang.UUID; import com.google.common.base.Preconditions; import lombok.extern.slf4j.Slf4j; import net.coobird.thumbnailator.Thumbnails; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.FileCopyUtils; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import javax.servlet.http.HttpServletResponse; import java.awt.image.BufferedImage; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.zip.CRC32; import java.util.zip.CheckedOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * @author MrBird */ @Slf4j public class FileUtil { private static final int BUFFER = 1024 * 8; /** * 文件上传服务器本地路径 */ public static Map fileUploadEsc(MultipartFile file,String resourceUrl,String resourcePath) throws IOException { // 文件保存目录路径 String savePath = resourcePath; // 文件保存目录URL String saveUrl = resourceUrl; // 检查目录 File uploadDir = new File(savePath); if (!uploadDir.isDirectory()) { uploadDir.mkdir(); } // 获得文件的后缀 String fileName = file.getOriginalFilename(); String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1); String newFileName = UUID.randomUUID().toString() + "." + fileExt; if (isImage(file.getInputStream())) { Thumbnails.of(file.getInputStream()) // 图片大小(长宽)压缩比例 从0-1,1表示原图 .scale(1f) // 图片质量压缩比例 从0-1,越接近1质量越好 .outputQuality(0.9f) .toOutputStream(new FileOutputStream(savePath + newFileName)); } else { File uploadedFile = new File(savePath, newFileName); uploadedFile.setReadable(true, false); uploadedFile.setExecutable(true, false); uploadedFile.setWritable(true, false); try { //存文件 FileCopyUtils.copy(file.getBytes(), uploadedFile); file.transferTo(uploadedFile); } catch (IOException e) { e.printStackTrace(); } } String visitPath = (saveUrl + newFileName); Map map = new HashMap(); Map map2 = new HashMap(); map2.put("src",visitPath);//图片url map2.put("title",newFileName);//图片名称,这个会显示在输入框里 map.put("code",0);//0表示成功,1失败 map.put("msg","上传成功");//提示消息 map.put("data",map2); return map; } public static boolean isImage(InputStream inputStream) { BufferedImage read = null; try { read = ImageIO.read(inputStream); } catch (IOException e) { return false; } return read != null; } /** * 压缩文件或目录 * * @param fromPath 待压缩文件或路径 * @param toPath 压缩文件,如 xx.zip */ public static void compress(String fromPath, String toPath) throws IOException { File fromFile = new File(fromPath); File toFile = new File(toPath); if (!fromFile.exists()) { throw new FileNotFoundException(fromPath + "不存在!"); } try ( FileOutputStream outputStream = new FileOutputStream(toFile); CheckedOutputStream checkedOutputStream = new CheckedOutputStream(outputStream, new CRC32()); ZipOutputStream zipOutputStream = new ZipOutputStream(checkedOutputStream) ) { String baseDir = ""; compress(fromFile, zipOutputStream, baseDir); } } /** * 文件下载 * * @param filePath 待下载文件路径 * @param fileName 下载文件名称 * @param delete 下载后是否删除源文件 * @param response HttpServletResponse * @throws Exception Exception */ public static void download(String filePath, String fileName, Boolean delete, HttpServletResponse response) throws Exception { File file = new File(filePath); if (!file.exists()) { throw new Exception("文件未找到"); } String fileType = getFileType(file); if (!fileTypeIsValid(fileType)) { throw new Exception("暂不支持该类型文件下载"); } response.setHeader("Content-Disposition", "attachment;fileName=" + java.net.URLEncoder.encode(fileName, "utf-8")); response.setContentType("multipart/form-data"); response.setCharacterEncoding("utf-8"); try (InputStream inputStream = new FileInputStream(file); OutputStream os = response.getOutputStream()) { byte[] b = new byte[2048]; int length; while ((length = inputStream.read(b)) > 0) { os.write(b, 0, length); } } finally { if (delete) { delete(filePath); } } } /** * 递归删除文件或目录 * * @param filePath 文件或目录 */ public static void delete(String filePath) { File file = new File(filePath); if (file.isDirectory()) { File[] files = file.listFiles(); if (files != null) { Arrays.stream(files).forEach(f -> delete(f.getPath())); } } try { Files.delete(Paths.get(filePath)); } catch (IOException e) { log.error("删除失败", e); } } /** * 获取文件类型 * * @param file 文件 * @return 文件类型 * @throws Exception Exception */ private static String getFileType(File file) throws Exception { Preconditions.checkNotNull(file); if (file.isDirectory()) { throw new Exception("file不是文件"); } String fileName = file.getName(); return fileName.substring(fileName.lastIndexOf(".") + 1); } /** * 校验文件类型是否是允许下载的类型 * (出于安全考虑:https://github.com/wuyouzhuguli/FEBS-Shiro/issues/40) * * @param fileType fileType * @return Boolean */ private static Boolean fileTypeIsValid(String fileType) { Preconditions.checkNotNull(fileType); fileType = StringUtils.lowerCase(fileType); return ArrayUtils.contains(FebsConstant.VALID_FILE_TYPE, fileType); } private static void compress(File file, ZipOutputStream zipOut, String baseDir) throws IOException { if (file.isDirectory()) { compressDirectory(file, zipOut, baseDir); } else { compressFile(file, zipOut, baseDir); } } private static void compressDirectory(File dir, ZipOutputStream zipOut, String baseDir) throws IOException { File[] files = dir.listFiles(); if (files != null && ArrayUtils.isNotEmpty(files)) { for (File file : files) { compress(file, zipOut, baseDir + dir.getName() + "/"); } } } private static void compressFile(File file, ZipOutputStream zipOut, String baseDir) throws IOException { if (!file.exists()) { return; } try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) { ZipEntry entry = new ZipEntry(baseDir + file.getName()); zipOut.putNextEntry(entry); int count; byte[] data = new byte[BUFFER]; while ((count = bis.read(data, 0, BUFFER)) != -1) { zipOut.write(data, 0, count); } } } }