package com.test.file.utils;
import com.test.commons.rest.RestErrorEnum;
import com.test.commons.rest.RestException;
import com.test.file.entity.FileInfo;
import com.test.filestruct.plm.file.DocxStructExplorer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.poi.util.IOUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@Slf4j
public class CustomFileUtils {
// office
private static String[] office = {"word", "excel", "ppt"};
// excel
private static String[] etExts = {"et", "xls", "xlt", "xlsx", "xlsm", "xltx", "xltm", "csv"};
// word
private static String[] wpsExts = {"doc", "docx", "txt", "dot", "wps", "wpt", "dotx", "docm", "dotm"};
// ppt
private static String[] wppExts = {"ppt", "pptx", "pptm", "pptm", "ppsm", "pps", "potx", "potm", "dpt", "dps"};
// pdf
private static String[] pdfExts = {"pdf"};
public static String getFileTypeCode(String fileType) {
for (String et : etExts) {
if (et.equalsIgnoreCase(fileType)) {
return "s";
}
}
for (String et : wpsExts) {
if (et.equalsIgnoreCase(fileType)) {
return "w";
}
}
for (String et : wppExts) {
if (et.equalsIgnoreCase(fileType)) {
return "p";
}
}
for (String et : pdfExts) {
if (et.equalsIgnoreCase(fileType)) {
return "f";
}
}
return null;
}
public static boolean checkCode(String fileType) {
for (String et : office) {
if (et.equalsIgnoreCase(fileType)) {
return true;
}
}
return false;
}
public static String getTypeCode(String fileType) {
if ("word".equalsIgnoreCase(fileType)) {
return "w";
}
if ("excel".equalsIgnoreCase(fileType)) {
return "s";
}
if ("ppt".equalsIgnoreCase(fileType)) {
return "p";
}
return null;
}
public static String getFileName(String filePath) {
String[] pathArr = filePath.split("/");
String fileName;
if (pathArr.length > 1) {
fileName = pathArr[pathArr.length - 1];
} else {
fileName = filePath;
}
return fileName;
}
public static String getFileTypeByPath(String filePath) {
String fileName = getFileName(filePath);
String[] arr = fileName.split("\.");
return arr[arr.length - 1];
}
public static String getFileTypeByName(String fileName) {
String[] arr = fileName.split("\.");
return arr[arr.length - 1];
}
public static String getFileUUIDName(String fileName, String fileType) {
String uuid = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
String uuidFileName = fileName.replace(".", "").replace(fileType, "") + uuid + "." + fileType;
return new String(uuidFileName.getBytes(), StandardCharsets.UTF_8);
}
public static void uploadFile(MultipartFile file, String path) {
try {
File dest = new File(path);
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
file.transferTo(dest);
// 加密上传文件
DocxStructExplorer.encryptFile(dest);
} catch (IOException e) {
log.error(e.getMessage());
throw new RestException(RestErrorEnum.FILE_UPLOAD_FAIL);
}
}
public static void download(String path, HttpServletRequest request, HttpServletResponse response, String fileName) {
File file = new File(path);
try {
// 获取加密文件解密之后的字节数组信息
byte[] data = DocxStructExplorer.decryptFile(file);
download(data, request, response, fileName);
} catch (IOException e) {
log.error("解密文件{}异常,{}", fileName, e.getMessage());
}
}
public static String getApplicationPath() {
return System.getProperty("user.dir");
}
public static void download(File file, HttpServletRequest request, HttpServletResponse response, String fileName) {
if (file.exists()) {
setHeader(request, response, fileName);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
IOUtils.copy(fis, response.getOutputStream());
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public static void download(byte[] data, HttpServletRequest request, HttpServletResponse response, String fileName) {
if (data != null) {
setHeader(request, response, fileName);
FileInputStream fis = null;
try {
ServletOutputStream out = response.getOutputStream();
out.write(data);
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public static void toZip(File zipFile, List srcFiles) {
ZipOutputStream zos = null;
try {
// 构造最终压缩包输出流
zos = new ZipOutputStream(new FileOutputStream(zipFile));
putFile(zos, srcFiles, null);
} catch (Exception e) {
log.error(e.getMessage());
throw new RestException(RestErrorEnum.FILE_DOWNLOAD_FAIL);
} finally {
if (zos != null) {
try {
zos.close();
} catch (IOException e) {
log.error(e.getMessage());
e.printStackTrace();
}
}
}
}
public static void putFile(ZipOutputStream zos, List srcFiles, String path) throws IOException {
path = StringUtils.isEmpty(path) ? "" : path;
for (FileInfo srcFile : srcFiles) {
putPrivateFile(zos, path + URLDecoder.decode(srcFile.getName(), "UTF-8"), srcFile.getPath());
}
}
public static void putPrivateFile(ZipOutputStream zos, String name, String path) throws IOException {
zos.putNextEntry(new ZipEntry(name));
// 获取加密文件解密后自己数组
byte[] data = DocxStructExplorer.decryptFile(new File(path));
InputStream input = new ByteArrayInputStream(data);
IOUtils.copy(input, zos);
zos.closeEntry();
if (input != null) {
input.close();
}
}
public static void putPublicFile(ZipOutputStream zos, String name, String path) throws IOException {
zos.putNextEntry(new ZipEntry(name));
// 获取加密文件解密后自己数组
InputStream input = new FileInputStream(new File(path));
IOUtils.copy(input, zos);
zos.closeEntry();
if (input != null) {
input.close();
}
}
public static void putPublicFile(ZipOutputStream zos, File file) throws IOException {
zos.putNextEntry(new ZipEntry(file.getName()));
// 获取加密文件解密后自己数组
InputStream input = new FileInputStream(file);
IOUtils.copy(input, zos);
zos.closeEntry();
if (input != null) {
input.close();
}
}
public static void zipFiles(String source, String dest) {
File file = new File(source);
ZipOutputStream zipOutputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(dest);
zipOutputStream = new ZipOutputStream(fileOutputStream);
if (file.isDirectory()) {
directory(zipOutputStream, file, "");
} else {
zipDirectoryFile(zipOutputStream, file, "");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
zipOutputStream.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void directory(ZipOutputStream zipOutputStream, File file, String parentFileName) {
File[] files = file.listFiles();
String parentFileNameTemp = null;
for (File fileTemp : files) {
parentFileNameTemp = StringUtils.isEmpty(parentFileName) ? fileTemp.getName() : parentFileName + "/" + fileTemp.getName();
if (fileTemp.isDirectory()) {
directory(zipOutputStream, fileTemp, parentFileNameTemp);
} else {
zipDirectoryFile(zipOutputStream, fileTemp, parentFileNameTemp);
}
}
}
public static void zipDirectoryFile(ZipOutputStream zipOutputStream, File file, String parentFileName) {
FileInputStream in = null;
try {
ZipEntry zipEntry = new ZipEntry(parentFileName);
zipOutputStream.putNextEntry(zipEntry);
in = new FileInputStream(file);
int len;
byte[] buf = new byte[8 * 1024];
while ((len = in.read(buf)) != -1) {
zipOutputStream.write(buf, 0, len);
}
zipOutputStream.closeEntry();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static boolean unZip(String zip, String targetPath) {
ZipFile zipFile = null;
int BUFFER_SIZE = 1024;
try {
zipFile = new ZipFile(zip, "gbk");//一般window用户默认是GBK,如果要更改编码,需要用winrar等软件压缩
Enumeration entries = zipFile.getEntries();
ZipArchiveEntry entry = null;
while (entries.hasMoreElements()) {
entry = entries.nextElement();
if (entry.isDirectory()) {
File directory = new File(targetPath, entry.getName());
directory.mkdirs();
} else {
File file = new File(targetPath, entry.getName());
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
InputStream is = zipFile.getInputStream(entry);
OutputStream os = new BufferedOutputStream(new FileOutputStream(file), BUFFER_SIZE);
IOUtils.copy(is, os);
IOUtils.closeQuietly(os);
IOUtils.closeQuietly(is);
}
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
zipFile.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private static boolean setHeader(HttpServletRequest request, HttpServletResponse response, String fileName) {
try {
response.setContentType("application/octet-stream");
response.setHeader("content-type", "application/octet-stream");
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
String browser = request.getHeader("User-Agent");
if (-1 < browser.indexOf("MSIE 6.0") || -1 < browser.indexOf("MSIE 7.0")) {
// IE6, IE7 浏览器
response.addHeader("content-disposition", "attachment; filename=" + new String(fileName.getBytes(), "ISO8859-1"));
} else if (-1 < browser.indexOf("MSIE 8.0")) {
// IE8
response.addHeader("content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")
.replaceAll("\+", " "));
} else if (-1 < browser.indexOf("MSIE 9.0")) {
// IE9
response.addHeader("content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")
.replaceAll("\+", " "));
} else if (-1 < browser.indexOf("Chrome")) {
// 谷歌
response.addHeader("content-disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8")
.replaceAll("\+", " "));
} else if (-1 < browser.indexOf("Safari")) {
// 苹果
response.addHeader("content-disposition", "attachment; filename=" + new String(fileName.getBytes(), "ISO8859-1"));
} else {
// 火狐或者其他的浏览器
response.addHeader("content-disposition", "attachment; filename*=UTF-8''" + URLEncoder.encode(fileName, "UTF-8")
.replaceAll("\+", " "));
}
return true;
} catch (Exception e) {
log.error(e.getMessage());
return false;
}
}
public static void deleteFile(String path) {
File file = new File(path);
if (file != null && file.exists() && file.isFile()) {
if (file.delete()) {
log.info("删除" + path + "草稿文档成功");
} else {
log.error("删除" + path + "草稿文档失败");
}
}
}
public static void setFileStreamToResponse(HttpServletResponse response, File zipFile) throws IOException {
FileInputStream fis = new FileInputStream(zipFile);
// force-download
response.setContentType("application/force-download");
response.setHeader("Content-Disposition", "attachment;filename="
.concat(String.valueOf(URLEncoder.encode(zipFile.getName(), "UTF-8"))));
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setCharacterEncoding("utf-8");
OutputStream os = response.getOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
os.write(buf, 0, len);
}
fis.close();
os.close();
}
public static void deleteFile(File file) {
if (file != null && file.exists() && file.isFile()) {
if (file.delete()) {
log.info("删除临时文件成功");
} else {
log.error("删除临时文件失败");
}
}
}
public static void copy(File file, File toFile) throws Exception {
byte[] b = new byte[1024];
int a;
FileInputStream fis;
FileOutputStream fos;
if (file.isDirectory()) {
String filepath = file.getAbsolutePath();
filepath = filepath.replaceAll("\\", "/");
String toFilepath = toFile.getAbsolutePath();
toFilepath = toFilepath.replaceAll("\\", "/");
int lastIndexOf = filepath.lastIndexOf("/");
toFilepath = toFilepath + filepath.substring(lastIndexOf, filepath.length());
File copy = new File(toFilepath);
//复制文件夹
if (!copy.exists()) {
copy.mkdir();
}
//遍历文件夹
for (File f : file.listFiles()) {
copy(f, copy);
}
} else {
if (toFile.isDirectory()) {
String filepath = file.getAbsolutePath();
filepath = filepath.replaceAll("\\", "/");
String toFilepath = toFile.getAbsolutePath();
toFilepath = toFilepath.replaceAll("\\", "/");
int lastIndexOf = filepath.lastIndexOf("/");
toFilepath = toFilepath + filepath.substring(lastIndexOf, filepath.length());
//写文件
File newFile = new File(toFilepath);
fis = new FileInputStream(file);
fos = new FileOutputStream(newFile);
while ((a = fis.read(b)) != -1) {
fos.write(b, 0, a);
}
} else {
//写文件
fis = new FileInputStream(file);
fos = new FileOutputStream(toFile);
while ((a = fis.read(b)) != -1) {
fos.write(b, 0, a);
}
}
}
}
public static void delDir(File file) {
if (file.isDirectory()) {
File zFiles[] = file.listFiles();
for (File file2 : zFiles) {
delDir(file2);
}
//删除目录
file.delete();
} else {
boolean delete = file.delete();
if(!delete){
log.error("文件删除失败");
}
}
}
}
package com.test.filestruct.plm.file;
import com.test.filestruct.plm.file.exception.EncryptException;
import com.test.filestruct.plm.file.exception.NoContentException;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class DocxStructExplorer {
private static final String STRUCT_PATH = "struct";
private static final String TABLE_PATH = "table";
private static final String PIC_PATH = "pic";
// 线上存储结构化数据的根目录。
private static boolean rootSet;
private static File root = new File(System.getProperty("user.dir") + "/files-prod/docx-struct");
public static void setRoot(File root) {
if (!rootSet) {
DocxStructExplorer.root = root;
}
rootSet = true;
}
public static File getRoot() {
return root;
}
public static File getTempPath() {
File file = new File(getRoot(), "temp");
if (!file.exists()) {
file.mkdirs();
}
return file;
}
public static File getProjectRoot(long projectId) {
return new File(getRoot(), projectId + "");
}
public static File getFileRoot(long projectId, long fileId) {
return new File(getRoot(), projectId + "/" + fileId);
}
public static File getVersionPath(long projectId, long fileId, String version) {
return new File(getRoot(), projectId + "/" + fileId + "/" + version);
}
public static File getFilePath(long projectId, long fileId) {
return new File(getRoot(), projectId + "/" + fileId);
}
public static File getStructPath(long projectId, long fileId, String version) {
return new File(getVersionPath(projectId, fileId, version), STRUCT_PATH);
}
public static File getTablePath(long projectId, long fileId) {
return new File(getFilePath(projectId, fileId), TABLE_PATH);
}
public static File getPicPath(long projectId, long fileId, String version) {
return new File(getVersionPath(projectId, fileId, version), PIC_PATH);
}
private static String getIndexStructFilename(int index) {
return index + ".struct";
}
private static String getIndexTableFilename(int index) {
return index + ".html";
}
private static String getViewFilename() {
return "view.html";
}
public static void encryptFile(File file) throws IOException {
if (file.exists()) {
byte[] bytes = FileUtils.readFileToByteArray(file);
if (bytes != null) {
Explorer.writeFile(file, bytes);
}
}
}
public static byte[] decryptFile(File file) throws IOException {
return Explorer.readFile(file);
}
public static byte[] readStruct(long projectId, long fileId, String version, int index) throws FileNotFoundException, IOException {
File file = new File(getStructPath(projectId, fileId, version), getIndexStructFilename(index));
return Explorer.readFile(file);
}
public static byte[] readTable(long projectId, long fileId, int index) throws FileNotFoundException, IOException {
File file = new File(getTablePath(projectId, fileId), getIndexTableFilename(index));
return Explorer.readFile(file);
}
public static void writeStruct(long projectId, long fileId, String version, int index, byte[] data) throws EncryptException, IOException {
File file = new File(getStructPath(projectId, fileId, version), getIndexStructFilename(index));
Explorer.writeFile(file, data);
}
public static void writeTable(long projectId, long fileId, int index, byte[] data) throws EncryptException, IOException {
File file = new File(getTablePath(projectId, fileId), getIndexTableFilename(index));
Explorer.writeFile(file, data);
}
public static String readView(long projectId, long fileId, String version) throws FileNotFoundException, IOException {
File file = new File(getVersionPath(projectId, fileId, version), getViewFilename());
byte[] data = Explorer.readFile(file);
if (data != null) {
return new String(data, StandardCharsets.UTF_8);
}
return null;
}
public static void writeView(long projectId, long fileId, String version, String html) throws IOException {
if (StringUtils.isEmpty(html)) {
throw new NoContentException();
}
File file = new File(getVersionPath(projectId, fileId, version), getViewFilename());
byte[] bytes = html.getBytes(StandardCharsets.UTF_8);
Explorer.writeFile(file, bytes);
}
public static void clearProject(long projectId) throws IOException {
File file = getProjectRoot(projectId);
FileUtils.deleteDirectory(file);
}
public static void clearFile(long projectId, long fileId) throws IOException {
File file = getFileRoot(projectId, fileId);
FileUtils.deleteDirectory(file);
}
public static void clearVersion(long projectId, long fileId, String version) throws IOException {
clearStruct(projectId, fileId, version);
deleteView(projectId, fileId, version);
}
public static boolean deleteStruct(long projectId, long fileId, String version, int index) {
return new File(getStructPath(projectId, fileId, version), getIndexStructFilename(index)).delete();
}
public static void clearStruct(long projectId, long fileId, String version) throws IOException {
FileUtils.deleteDirectory(getStructPath(projectId, fileId, version));
}
public static boolean deleteView(long projectId, long fileId, String version) {
return new File(getVersionPath(projectId, fileId, version), getViewFilename()).delete();
}
}
1.CustomFileUtils :文件操作,当中的自定义异常类本文中没有写入,参考者可自行替换
2.DocxStructExplorer:word 文件的相关处理,文件操作的工具类中有调用本类的加密、解密方法



