mirror of
https://gitee.com/kekingcn/file-online-preview.git
synced 2026-03-17 06:33:50 +08:00
1.修改包结构为cn.keking,
2.新增压缩包内文件名称排序
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import com.sun.star.document.UpdateDocMode;
|
||||
import cn.keking.extend.ControlDocumentFormatRegistry;
|
||||
import org.artofsolving.jodconverter.OfficeDocumentConverter;
|
||||
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
|
||||
import org.artofsolving.jodconverter.office.OfficeManager;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 创建文件转换器
|
||||
*
|
||||
* @author yudian-it
|
||||
* @date 2017/11/13
|
||||
*/
|
||||
@Component
|
||||
public class ConverterUtils {
|
||||
|
||||
@Value("${office.home}")
|
||||
String officeHome;
|
||||
// OpenOfficeConnection connection;
|
||||
OfficeManager officeManager;
|
||||
|
||||
@PostConstruct
|
||||
public void initOfficeManager() {
|
||||
//// connection = new SocketOpenOfficeConnection(host,8100);
|
||||
//// connection.connect();
|
||||
DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
|
||||
configuration.setOfficeHome(officeHome);
|
||||
configuration.setPortNumber(8100);
|
||||
officeManager = configuration.buildOfficeManager();
|
||||
officeManager.start();
|
||||
// 设置任务执行超时为5分钟
|
||||
// configuration.setTaskExecutionTimeout(1000 * 60 * 5L);//
|
||||
// 设置任务队列超时为24小时
|
||||
// configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L);//
|
||||
}
|
||||
|
||||
public OfficeDocumentConverter getDocumentConverter() {
|
||||
OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager, new ControlDocumentFormatRegistry());
|
||||
converter.setDefaultLoadProperties(getLoadProperties());
|
||||
return converter;
|
||||
}
|
||||
|
||||
private Map<String,?> getLoadProperties() {
|
||||
Map<String,Object> loadProperties = new HashMap<>(10);
|
||||
loadProperties.put("Hidden", true);
|
||||
loadProperties.put("ReadOnly", true);
|
||||
loadProperties.put("UpdateDocMode", UpdateDocMode.QUIET_UPDATE);
|
||||
loadProperties.put("CharacterSet", Charset.forName("UTF-8").name());
|
||||
return loadProperties;
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroyOfficeManager(){
|
||||
if (null != officeManager && officeManager.isRunning()) {
|
||||
officeManager.stop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class DeleteFileUtil {
|
||||
/**
|
||||
* 删除单个文件
|
||||
*
|
||||
* @param fileName
|
||||
* 要删除的文件的文件名
|
||||
* @return 单个文件删除成功返回true,否则返回false
|
||||
*/
|
||||
public static boolean deleteFile(String fileName) {
|
||||
File file = new File(fileName);
|
||||
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
|
||||
if (file.exists() && file.isFile()) {
|
||||
if (file.delete()) {
|
||||
System.out.println("删除单个文件" + fileName + "成功!");
|
||||
return true;
|
||||
} else {
|
||||
System.out.println("删除单个文件" + fileName + "失败!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
System.out.println("删除单个文件失败:" + fileName + "不存在!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除目录及目录下的文件
|
||||
*
|
||||
* @param dir
|
||||
* 要删除的目录的文件路径
|
||||
* @return 目录删除成功返回true,否则返回false
|
||||
*/
|
||||
public static boolean deleteDirectory(String dir) {
|
||||
// 如果dir不以文件分隔符结尾,自动添加文件分隔符
|
||||
if (!dir.endsWith(File.separator)) {
|
||||
dir = dir + File.separator;
|
||||
}
|
||||
File dirFile = new File(dir);
|
||||
// 如果dir对应的文件不存在,或者不是一个目录,则退出
|
||||
if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
|
||||
System.out.println("删除目录失败:" + dir + "不存在!");
|
||||
return false;
|
||||
}
|
||||
boolean flag = true;
|
||||
// 删除文件夹中的所有文件包括子目录
|
||||
File[] files = dirFile.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
// 删除子文件
|
||||
if (files[i].isFile()) {
|
||||
flag = DeleteFileUtil.deleteFile(files[i].getAbsolutePath());
|
||||
if (!flag)
|
||||
break;
|
||||
}
|
||||
// 删除子目录
|
||||
else if (files[i].isDirectory()) {
|
||||
flag = DeleteFileUtil.deleteDirectory(files[i]
|
||||
.getAbsolutePath());
|
||||
if (!flag)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
System.out.println("删除目录失败!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import cn.keking.param.ReturnResponse;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author yudian-it
|
||||
*/
|
||||
@Component
|
||||
public class DownloadUtils {
|
||||
|
||||
@Value("${file.dir}")
|
||||
String fileDir;
|
||||
|
||||
/**
|
||||
* 一开始测试的时候发现有些文件没有下载下来,而有些可以;当时也是郁闷了好一阵,但是最终还是不得解
|
||||
* 再次测试的时候,通过前台对比url发现,原来参数中有+号特殊字符存在,但是到后之后却变成了空格,突然恍然大悟
|
||||
* 应该是转义出了问题,url转义中会把+号当成空格来计算,所以才会出现这种情况,遂想要通过整体替换空格为加号,因为url
|
||||
* 中的参数部分是不会出现空格的,但是文件名中就不好确定了,所以只对url参数部分做替换
|
||||
* 注: 针对URLEncoder.encode(s,charset)会将空格转成+的情况需要做下面的替换工作
|
||||
* @param urlAddress
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
public ReturnResponse<String> downLoad(String urlAddress, String type, String fileName){
|
||||
ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", "");
|
||||
URL url = null;
|
||||
try {
|
||||
urlAddress = replacePlusMark(urlAddress);
|
||||
urlAddress = encodeUrlParam(urlAddress);
|
||||
// 因为tomcat不能处理'+'号,所以讲'+'号替换成'%20%'
|
||||
urlAddress = urlAddress.replaceAll("\\+", "%20");
|
||||
url = new URL(urlAddress);
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
UUID uuid = UUID.randomUUID();
|
||||
if (null == fileName) {
|
||||
fileName = uuid+ "."+type;
|
||||
}else { // 文件后缀不一致时,以type为准(针对simText【将类txt文件转为txt】)
|
||||
fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type);
|
||||
}
|
||||
String realPath = fileDir + fileName;
|
||||
File dirFile = new File(fileDir);
|
||||
if (!dirFile.exists()) {
|
||||
dirFile.mkdirs();
|
||||
}
|
||||
try {
|
||||
URLConnection connection = url.openConnection();
|
||||
InputStream in = connection.getInputStream();
|
||||
|
||||
FileOutputStream os = new FileOutputStream(realPath);
|
||||
byte[] buffer = new byte[4 * 1024];
|
||||
int read;
|
||||
while ((read = in.read(buffer)) > 0) {
|
||||
os.write(buffer, 0, read);
|
||||
}
|
||||
os.close();
|
||||
in.close();
|
||||
response.setContent(realPath);
|
||||
// 同样针对类txt文件,如果成功msg包含的是转换后的文件名
|
||||
response.setMsg(fileName);
|
||||
|
||||
// txt转换文件编码为utf8
|
||||
if("txt".equals(type)){
|
||||
convertTextPlainFileCharsetToUtf8(realPath);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
response.setCode(1);
|
||||
response.setContent(null);
|
||||
if (e instanceof FileNotFoundException) {
|
||||
response.setMsg("文件不存在!!!");
|
||||
}else {
|
||||
response.setMsg(e.getMessage());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注:可能是原来因为前端通过encodeURI来编码的,因为通过encodeURI编码+会被转成+号(亦即没有转),
|
||||
* 而通过encodeURIComponent则会转成%2B,这样URLDecoder是可以正确处理的,所以也就没有必要在这里替换了
|
||||
* 转换url参数部分的空格为加号(因为在url编解码的过程中出现+转为空格的情况)
|
||||
* @param urlAddress
|
||||
* @return
|
||||
*/
|
||||
private String replacePlusMark(String urlAddress) {
|
||||
if (urlAddress.contains("?")) {
|
||||
String nonParamStr = urlAddress.substring(0,urlAddress.indexOf("?") + 1);
|
||||
String paramStr = urlAddress.substring(nonParamStr.length());
|
||||
return nonParamStr + paramStr.replace(" ", "+");
|
||||
}
|
||||
return urlAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对最有一个路径进行转码
|
||||
* @param urlAddress
|
||||
* http://192.168.2.111:8013/demo/Handle中文.zip
|
||||
* @return
|
||||
*/
|
||||
private String encodeUrlParam(String urlAddress) {
|
||||
String newUrl = "";
|
||||
try {
|
||||
String path = "";
|
||||
String param = "";
|
||||
if (urlAddress.contains("?")) {
|
||||
path = urlAddress.substring(0, urlAddress.indexOf("?"));
|
||||
param = urlAddress.substring(urlAddress.indexOf("?"));
|
||||
}else {
|
||||
path = urlAddress;
|
||||
}
|
||||
String lastPath = path.substring(path.lastIndexOf("/") + 1);
|
||||
String leftPath = path.substring(0, path.lastIndexOf("/") + 1);
|
||||
String encodeLastPath = URLEncoder.encode(lastPath, "UTF-8");
|
||||
newUrl += leftPath + encodeLastPath;
|
||||
if (urlAddress.contains("?")) {
|
||||
newUrl += param;
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return newUrl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 因为jodConvert2.1不支持ms2013版本的office转换,这里偷懒,尝试看改一下文件类型,让jodConvert2.1去
|
||||
* 处理ms2013,看结果如何,如果问题很大的话只能采取其他方式,如果没有问题,暂时使用该版本来转换
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private String dealWithMS2013(String type) {
|
||||
String newType = null;
|
||||
switch (type){
|
||||
case "docx":
|
||||
newType = "doc";
|
||||
break;
|
||||
case "xlsx":
|
||||
newType = "doc";
|
||||
break;
|
||||
case "pptx":
|
||||
newType = "ppt";
|
||||
break;
|
||||
default:
|
||||
newType = type;
|
||||
break;
|
||||
}
|
||||
return newType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换文本文件编码为utf8
|
||||
* 探测源文件编码,探测到编码切不为utf8则进行转码
|
||||
* @param filePath 文件路径
|
||||
*/
|
||||
private static void convertTextPlainFileCharsetToUtf8(String filePath) throws IOException {
|
||||
File sourceFile = new File(filePath);
|
||||
if(sourceFile.exists() && sourceFile.isFile() && sourceFile.canRead()) {
|
||||
String encoding = null;
|
||||
try {
|
||||
FileCharsetDetector.Observer observer = FileCharsetDetector.guessFileEncoding(sourceFile);
|
||||
// 为准确探测到编码,不适用猜测的编码
|
||||
encoding = observer.isFound()?observer.getEncoding():null;
|
||||
// 为准确探测到编码,可以考虑使用GBK 大部分文件都是windows系统产生的
|
||||
} catch (IOException e) {
|
||||
// 编码探测失败,
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(encoding != null && !"UTF-8".equals(encoding)){
|
||||
// 不为utf8,进行转码
|
||||
File tmpUtf8File = new File(filePath+".utf8");
|
||||
Writer writer = new OutputStreamWriter(new FileOutputStream(tmpUtf8File),"UTF-8");
|
||||
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sourceFile),encoding));
|
||||
char[] buf = new char[1024];
|
||||
int read;
|
||||
while ((read = reader.read(buf)) > 0){
|
||||
writer.write(buf, 0, read);
|
||||
}
|
||||
reader.close();
|
||||
writer.close();
|
||||
// 删除源文件
|
||||
sourceFile.delete();
|
||||
// 重命名
|
||||
tmpUtf8File.renameTo(sourceFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.mozilla.intl.chardet.nsDetector;
|
||||
import org.mozilla.intl.chardet.nsICharsetDetectionObserver;
|
||||
|
||||
/**
|
||||
* 文本文件编码探测工具类
|
||||
*
|
||||
* @author HWliao
|
||||
* @date 2017-12-24
|
||||
*/
|
||||
public class FileCharsetDetector {
|
||||
|
||||
/**
|
||||
* 传入一个文件(File)对象,检查文件编码
|
||||
*
|
||||
* @param file File对象实例
|
||||
* @return 文件编码,若无,则返回null
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Observer guessFileEncoding(File file)
|
||||
throws FileNotFoundException, IOException {
|
||||
return guessFileEncoding(file, new nsDetector());
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 获取文件的编码
|
||||
* @param file
|
||||
* File对象实例
|
||||
* @param languageHint
|
||||
* 语言提示区域代码 @see #nsPSMDetector ,取值如下:
|
||||
* 1 : Japanese
|
||||
* 2 : Chinese
|
||||
* 3 : Simplified Chinese
|
||||
* 4 : Traditional Chinese
|
||||
* 5 : Korean
|
||||
* 6 : Dont know(default)
|
||||
* </pre>
|
||||
*
|
||||
* @return 文件编码,eg:UTF-8,GBK,GB2312形式(不确定的时候,返回可能的字符编码序列);若无,则返回null
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Observer guessFileEncoding(File file, int languageHint)
|
||||
throws FileNotFoundException, IOException {
|
||||
return guessFileEncoding(file, new nsDetector(languageHint));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的编码
|
||||
*
|
||||
* @param file
|
||||
* @param det
|
||||
* @return
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
private static Observer guessFileEncoding(File file, nsDetector det)
|
||||
throws FileNotFoundException, IOException {
|
||||
// new Observer
|
||||
Observer observer = new Observer();
|
||||
// set Observer
|
||||
// The Notify() will be called when a matching charset is found.
|
||||
det.Init(observer);
|
||||
|
||||
BufferedInputStream imp = new BufferedInputStream(new FileInputStream(
|
||||
file));
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
boolean done = false;
|
||||
boolean isAscii = false;
|
||||
|
||||
while ((len = imp.read(buf, 0, buf.length)) != -1) {
|
||||
// Check if the stream is only ascii.
|
||||
isAscii = det.isAscii(buf, len);
|
||||
if (isAscii) {
|
||||
break;
|
||||
}
|
||||
// DoIt if non-ascii and not done yet.
|
||||
done = det.DoIt(buf, len, false);
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
imp.close();
|
||||
det.DataEnd();
|
||||
|
||||
if (isAscii) {
|
||||
observer.encoding = "ASCII";
|
||||
observer.found = true;
|
||||
}
|
||||
|
||||
if (!observer.isFound()) {
|
||||
String[] prob = det.getProbableCharsets();
|
||||
// // 这里将可能的字符集组合起来返回
|
||||
// for (int i = 0; i < prob.length; i++) {
|
||||
// if (i == 0) {
|
||||
// encoding = prob[i];
|
||||
// } else {
|
||||
// encoding += "," + prob[i];
|
||||
// }
|
||||
// }
|
||||
if (prob.length > 0) {
|
||||
// 在没有发现情况下,去第一个可能的编码
|
||||
observer.encoding = prob[0];
|
||||
} else {
|
||||
observer.encoding = null;
|
||||
}
|
||||
}
|
||||
return observer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author liaohongwei
|
||||
* @Description: 文件字符编码观察者, 但判断出字符编码时候调用
|
||||
* @date 2016年6月20日 下午2:27:06
|
||||
*/
|
||||
public static class Observer implements nsICharsetDetectionObserver {
|
||||
|
||||
/**
|
||||
* @Fields encoding : 字符编码
|
||||
*/
|
||||
private String encoding = null;
|
||||
/**
|
||||
* @Fields found : 是否找到字符集
|
||||
*/
|
||||
private boolean found = false;
|
||||
|
||||
@Override
|
||||
public void Notify(String charset) {
|
||||
this.encoding = charset;
|
||||
this.found = true;
|
||||
}
|
||||
|
||||
public String getEncoding() {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public boolean isFound() {
|
||||
return found;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Observer [encoding=" + encoding + ", found=" + found + "]";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
238
jodconverter-web/src/main/java/cn/keking/utils/FileUtils.java
Normal file
238
jodconverter-web/src/main/java/cn/keking/utils/FileUtils.java
Normal file
@@ -0,0 +1,238 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.redisson.api.RMapCache;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author yudian-it
|
||||
* @date 2017/11/13
|
||||
*/
|
||||
@Component
|
||||
public class FileUtils {
|
||||
|
||||
final String REDIS_FILE_PREVIEW_PDF_KEY = "converted-preview-pdf-file";
|
||||
final String REDIS_FILE_PREVIEW_IMGS_KEY = "converted-preview-imgs-file";//压缩包内图片文件集合
|
||||
@Autowired
|
||||
RedissonClient redissonClient;
|
||||
@Value("${file.dir}")
|
||||
String fileDir;
|
||||
|
||||
@Value("${converted.file.charset}")
|
||||
String charset;
|
||||
|
||||
@Value("${simText}")
|
||||
String[] simText;
|
||||
/**
|
||||
* 已转换过的文件集合(redis缓存)
|
||||
* @return
|
||||
*/
|
||||
public Map<String, String> listConvertedFiles() {
|
||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
|
||||
return convertedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 已转换过的文件,根据文件名获取
|
||||
* @return
|
||||
*/
|
||||
public String getConvertedFile(String key) {
|
||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
|
||||
return convertedList.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查看文件类型(防止参数中存在.点号或者其他特殊字符,所以先抽取文件名,然后再获取文件类型)
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public String typeFromUrl(String url) {
|
||||
String nonPramStr = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?") : url.length());
|
||||
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
|
||||
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||
if (listPictureTypes().contains(fileType.toLowerCase())) {
|
||||
fileType = "picture";
|
||||
}
|
||||
if (listArchiveTypes().contains(fileType.toLowerCase())) {
|
||||
fileType = "compress";
|
||||
}
|
||||
if (listOfficeTypes().contains(fileType.toLowerCase())) {
|
||||
fileType = "office";
|
||||
}
|
||||
if (Arrays.asList(simText).contains(fileType.toLowerCase())) {
|
||||
fileType = "simText";
|
||||
}
|
||||
return fileType;
|
||||
}
|
||||
/**
|
||||
* 从url中剥离出文件名
|
||||
* @param url
|
||||
* 格式如:http://keking.ufile.ucloud.com.cn/20171113164107_月度绩效表模板(新).xls?UCloudPublicKey=ucloudtangshd@weifenf.com14355492830001993909323&Expires=&Signature=I D1NOFtAJSPT16E6imv6JWuq0k=
|
||||
* @return
|
||||
*/
|
||||
public String getFileNameFromURL(String url) {
|
||||
// 因为url的参数中可能会存在/的情况,所以直接url.lastIndexOf("/")会有问题
|
||||
// 所以先从?处将url截断,然后运用url.lastIndexOf("/")获取文件名
|
||||
String noQueryUrl = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?"): url.length());
|
||||
String fileName = noQueryUrl.substring(noQueryUrl.lastIndexOf("/") + 1);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件后缀
|
||||
* @param fileName
|
||||
* @return
|
||||
*/
|
||||
public String getSuffixFromFileName(String fileName) {
|
||||
String suffix = fileName.substring(fileName.lastIndexOf("."));
|
||||
return suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从路径中获取
|
||||
* @param path
|
||||
* 类似这种:C:\Users\yudian-it\Downloads
|
||||
* @return
|
||||
*/
|
||||
public String getFileNameFromPath(String path) {
|
||||
return path.substring(path.lastIndexOf(File.separator) + 1);
|
||||
}
|
||||
|
||||
public List<String> listPictureTypes(){
|
||||
List<String> list = Lists.newArrayList();
|
||||
list.add("jpg");
|
||||
list.add("jpeg");
|
||||
list.add("png");
|
||||
list.add("gif");
|
||||
list.add("bmp");
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<String> listArchiveTypes(){
|
||||
List<String> list = Lists.newArrayList();
|
||||
list.add("rar");
|
||||
list.add("zip");
|
||||
list.add("jar");
|
||||
list.add("7-zip");
|
||||
list.add("tar");
|
||||
list.add("gzip");
|
||||
list.add("7z");
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<String> listOfficeTypes() {
|
||||
List<String> list = Lists.newArrayList();
|
||||
list.add("docx");
|
||||
list.add("doc");
|
||||
list.add("xls");
|
||||
list.add("xlsx");
|
||||
list.add("ppt");
|
||||
list.add("pptx");
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取相对路径
|
||||
* @param absolutePath
|
||||
* @return
|
||||
*/
|
||||
public String getRelativePath(String absolutePath) {
|
||||
return absolutePath.substring(fileDir.length());
|
||||
}
|
||||
|
||||
public void addConvertedFile(String fileName, String value){
|
||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
|
||||
convertedList.fastPut(fileName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取redis中压缩包内图片文件
|
||||
* @param fileKey
|
||||
* @return
|
||||
*/
|
||||
public List getRedisImgUrls(String fileKey){
|
||||
RMapCache<String, List> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
|
||||
return convertedList.get(fileKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置redis中压缩包内图片文件
|
||||
* @param fileKey
|
||||
* @param imgs
|
||||
*/
|
||||
public void setRedisImgUrls(String fileKey,List imgs){
|
||||
RMapCache<String, List> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
|
||||
convertedList.fastPut(fileKey,imgs);
|
||||
}
|
||||
/**
|
||||
* 判断文件编码格式
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
public String getFileEncodeUTFGBK(String path){
|
||||
String enc = Charset.forName("GBK").name();
|
||||
File file = new File(path);
|
||||
InputStream in= null;
|
||||
try {
|
||||
in = new FileInputStream(file);
|
||||
byte[] b = new byte[3];
|
||||
in.read(b);
|
||||
in.close();
|
||||
if (b[0] == -17 && b[1] == -69 && b[2] == -65) {
|
||||
enc = Charset.forName("UTF-8").name();
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
System.out.println("文件编码格式为:" + enc);
|
||||
return enc;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对转换后的文件进行操作(改变编码方式)
|
||||
* @param outFilePath
|
||||
*/
|
||||
public void doActionConvertedFile(String outFilePath) {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
try (InputStream inputStream = new FileInputStream(outFilePath);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset))){
|
||||
String line;
|
||||
while(null != (line = reader.readLine())){
|
||||
if (line.contains("charset=gb2312")) {
|
||||
line = line.replace("charset=gb2312", "charset=utf-8");
|
||||
}
|
||||
sb.append(line);
|
||||
}
|
||||
// 添加sheet控制头
|
||||
sb.append("<script src=\"js/jquery-3.0.0.min.js\" type=\"text/javascript\"></script>");
|
||||
sb.append("<script src=\"js/excel.header.js\" type=\"text/javascript\"></script>");
|
||||
sb.append("<link rel=\"stylesheet\" href=\"http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css\">");
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// 重新写入文件
|
||||
try(FileOutputStream fos = new FileOutputStream(outFilePath);
|
||||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos))){
|
||||
writer.write(sb.toString());
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
112
jodconverter-web/src/main/java/cn/keking/utils/OfficeToPdf.java
Normal file
112
jodconverter-web/src/main/java/cn/keking/utils/OfficeToPdf.java
Normal file
@@ -0,0 +1,112 @@
|
||||
package cn.keking.utils;
|
||||
import org.artofsolving.jodconverter.OfficeDocumentConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author yudian-it
|
||||
*/
|
||||
@Component
|
||||
public class OfficeToPdf {
|
||||
/**
|
||||
* 获取OpenOffice.org 3的安装目录
|
||||
*
|
||||
* @return OpenOffice.org 3的安装目录
|
||||
*/
|
||||
@Autowired
|
||||
ConverterUtils converterUtils;
|
||||
/**
|
||||
* 使Office2003-2007全部格式的文档(.doc|.docx|.xls|.xlsx|.ppt|.pptx) 转化为pdf文件<br>
|
||||
*
|
||||
* @param inputFilePath
|
||||
* 源文件路径,如:"e:/test.docx"
|
||||
* @param outputFilePath
|
||||
* 目标文件路径,如:"e:/test_docx.pdf"
|
||||
* @return
|
||||
*/
|
||||
public boolean openOfficeToPDF(String inputFilePath, String outputFilePath) {
|
||||
return office2pdf(inputFilePath, outputFilePath);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换文件
|
||||
*
|
||||
* @param inputFile
|
||||
* @param outputFilePath_end
|
||||
* @param inputFilePath
|
||||
* @param outputFilePath
|
||||
* @param converter
|
||||
*/
|
||||
public static void converterFile(File inputFile, String outputFilePath_end,
|
||||
String inputFilePath, String outputFilePath,
|
||||
OfficeDocumentConverter converter) {
|
||||
File outputFile = new File(outputFilePath_end);
|
||||
// 假如目标路径不存在,则新建该路径
|
||||
if (!outputFile.getParentFile().exists()) {
|
||||
outputFile.getParentFile().mkdirs();
|
||||
}
|
||||
converter.convert(inputFile, outputFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使Office2003-2007全部格式的文档(.doc|.docx|.xls|.xlsx|.ppt|.pptx) 转化为pdf文件
|
||||
*
|
||||
* @param inputFilePath
|
||||
* 源文件路径,如:"e:/test.docx"
|
||||
* @param outputFilePath
|
||||
* 目标文件路径,如:"e:/test_docx.pdf"
|
||||
* @return
|
||||
*/
|
||||
public boolean office2pdf(String inputFilePath, String outputFilePath) {
|
||||
boolean flag = false;
|
||||
OfficeDocumentConverter converter = converterUtils.getDocumentConverter();
|
||||
if (null != inputFilePath) {
|
||||
File inputFile = new File(inputFilePath);
|
||||
// 判断目标文件路径是否为空
|
||||
if (null == outputFilePath) {
|
||||
// 转换后的文件路径
|
||||
String outputFilePath_end = getOutputFilePath(inputFilePath);
|
||||
if (inputFile.exists()) {// 找不到源文件, 则返回
|
||||
converterFile(inputFile, outputFilePath_end, inputFilePath,
|
||||
outputFilePath, converter);
|
||||
flag = true;
|
||||
}
|
||||
} else {
|
||||
if (inputFile.exists()) {// 找不到源文件, 则返回
|
||||
converterFile(inputFile, outputFilePath, inputFilePath,
|
||||
outputFilePath, converter);
|
||||
flag = true;
|
||||
}
|
||||
}
|
||||
// officeManager.stop();
|
||||
} else {
|
||||
flag = false;
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取输出文件
|
||||
*
|
||||
* @param inputFilePath
|
||||
* @return
|
||||
*/
|
||||
public static String getOutputFilePath(String inputFilePath) {
|
||||
String outputFilePath = inputFilePath.replaceAll("."
|
||||
+ getPostfix(inputFilePath), ".pdf");
|
||||
return outputFilePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取inputFilePath的后缀名,如:"e:/test.pptx"的后缀名为:"pptx"
|
||||
*
|
||||
* @param inputFilePath
|
||||
* @return
|
||||
*/
|
||||
public static String getPostfix(String inputFilePath) {
|
||||
return inputFilePath.substring(inputFilePath.lastIndexOf(".") + 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ShedulerClean {
|
||||
@Value("${file.dir}")
|
||||
String fileDir;
|
||||
|
||||
// @Scheduled(cron = "0 0 23 * * ?") //每晚23点执行一次
|
||||
public void clean(){
|
||||
System.out.println("执行一次清空文件夹");
|
||||
DeleteFileUtil.deleteDirectory(fileDir);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import cn.keking.param.ReturnResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 读取类文本文件
|
||||
* @author yudian-it
|
||||
* @date 2017/12/13
|
||||
*/
|
||||
@Component
|
||||
public class SimTextUtil {
|
||||
@Value("${file.dir}")
|
||||
String fileDir;
|
||||
@Autowired
|
||||
DownloadUtils downloadUtils;
|
||||
|
||||
public ReturnResponse<String> readSimText(String url, String fileName){
|
||||
ReturnResponse<String> response = downloadUtils.downLoad(url, "txt", fileName);
|
||||
return response;
|
||||
}
|
||||
}
|
||||
459
jodconverter-web/src/main/java/cn/keking/utils/ZipReader.java
Normal file
459
jodconverter-web/src/main/java/cn/keking/utils/ZipReader.java
Normal file
@@ -0,0 +1,459 @@
|
||||
package cn.keking.utils;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.junrar.Archive;
|
||||
import com.github.junrar.exception.RarException;
|
||||
import com.github.junrar.rarfile.FileHeader;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.CollationKey;
|
||||
import java.text.Collator;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author yudian-it
|
||||
* @date 2017/11/27
|
||||
*/
|
||||
@Component
|
||||
public class ZipReader {
|
||||
static Pattern pattern = Pattern.compile("^\\d+");
|
||||
|
||||
@Autowired
|
||||
FileUtils fileUtils;
|
||||
@Value("${file.dir}")
|
||||
String fileDir;
|
||||
|
||||
ExecutorService executors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
|
||||
/**
|
||||
* 读取压缩文件
|
||||
* 文件压缩到统一目录fileDir下,并且命名使用压缩文件名+文件名因为文件名
|
||||
* 可能会重复(在系统中对于同一种类型的材料压缩文件内的文件是一样的,如果文件名
|
||||
* 重复,那么这里会被覆盖[同一个压缩文件中的不同目录中的相同文件名暂时不考虑])
|
||||
* <b>注:</b>
|
||||
* <p>
|
||||
* 文件名命名中的参数的说明:
|
||||
* 1.archiveName,为避免解压的文件中有重名的文件会彼此覆盖,所以加上了archiveName,因为在ufile中archiveName
|
||||
* 是不会重复的。
|
||||
* 2.level,这里层级结构的列表我是通过一个map来构造的,map的key是文件的名字,值是对应的文件,这样每次向map中
|
||||
* 加入节点的时候都会获取父节点是否存在,存在则会获取父节点的value并将当前节点加入到父节点的childList中(这里利用
|
||||
* 的是java语言的引用的特性)。
|
||||
* </p>
|
||||
* @param filePath
|
||||
*/
|
||||
public String readZipFile(String filePath,String fileKey) {
|
||||
String archiveSeparator = "/";
|
||||
Map<String, FileNode> appender = Maps.newHashMap();
|
||||
List imgUrls=Lists.newArrayList();
|
||||
String baseUrl= (String) RequestContextHolder.currentRequestAttributes().getAttribute("baseUrl",0);
|
||||
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
|
||||
try {
|
||||
ZipFile zipFile = new ZipFile(filePath, fileUtils.getFileEncodeUTFGBK(filePath));
|
||||
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
|
||||
// 排序
|
||||
entries = sortZipEntries(entries);
|
||||
List<Map<String, ZipArchiveEntry>> entriesToBeExtracted = Lists.newArrayList();
|
||||
while (entries.hasMoreElements()){
|
||||
ZipArchiveEntry entry = entries.nextElement();
|
||||
String fullName = entry.getName();
|
||||
int level = fullName.split(archiveSeparator).length;
|
||||
// 展示名
|
||||
String originName = getLastFileName(fullName, archiveSeparator);
|
||||
String childName = level + "_" + originName;
|
||||
boolean directory = entry.isDirectory();
|
||||
if (!directory) {
|
||||
childName = archiveFileName + "_" + originName;
|
||||
entriesToBeExtracted.add(Collections.singletonMap(childName, entry));
|
||||
}
|
||||
String parentName = getLast2FileName(fullName, archiveSeparator, archiveFileName);
|
||||
parentName = (level-1) + "_" + parentName;
|
||||
String type=fileUtils.typeFromUrl(childName);
|
||||
if (type.equalsIgnoreCase("picture")){//添加图片文件到图片列表
|
||||
imgUrls.add(baseUrl+childName);
|
||||
}
|
||||
FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory,fileKey);
|
||||
addNodes(appender, parentName, node);
|
||||
appender.put(childName, node);
|
||||
}
|
||||
// 开启新的线程处理文件解压
|
||||
executors.submit(new ZipExtractorWorker(entriesToBeExtracted, zipFile, filePath));
|
||||
fileUtils.setRedisImgUrls(fileKey,imgUrls);
|
||||
return new ObjectMapper().writeValueAsString(appender.get(""));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 排序zipEntries(对原来列表倒序)
|
||||
* @param entries
|
||||
*/
|
||||
private Enumeration<ZipArchiveEntry> sortZipEntries(Enumeration<ZipArchiveEntry> entries) {
|
||||
List<ZipArchiveEntry> sortedEntries = Lists.newArrayList();
|
||||
while(entries.hasMoreElements()){
|
||||
sortedEntries.add(entries.nextElement());
|
||||
}
|
||||
Collections.sort(sortedEntries, Comparator.comparingInt(o -> o.getName().length()));
|
||||
return Collections.enumeration(sortedEntries);
|
||||
}
|
||||
|
||||
public String unRar(String filePath,String fileKey){
|
||||
Map<String, FileNode> appender = Maps.newHashMap();
|
||||
List imgUrls=Lists.newArrayList();
|
||||
String baseUrl= (String) RequestContextHolder.currentRequestAttributes().getAttribute("baseUrl",0);
|
||||
try {
|
||||
Archive archive = new Archive(new File(filePath));
|
||||
List<FileHeader> headers = archive.getFileHeaders();
|
||||
headers = sortedHeaders(headers);
|
||||
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
|
||||
List<Map<String, FileHeader>> headersToBeExtracted = Lists.newArrayList();
|
||||
for (FileHeader header : headers) {
|
||||
String fullName;
|
||||
if (header.isUnicode()) {
|
||||
fullName = header.getFileNameW();
|
||||
}else {
|
||||
fullName = header.getFileNameString();
|
||||
}
|
||||
// 展示名
|
||||
String originName = getLastFileName(fullName, "\\");
|
||||
String childName = originName;
|
||||
boolean directory = header.isDirectory();
|
||||
if (!directory) {
|
||||
childName = archiveFileName + "_" + originName;
|
||||
headersToBeExtracted.add(Collections.singletonMap(childName, header));
|
||||
}
|
||||
String parentName = getLast2FileName(fullName, "\\", archiveFileName);
|
||||
String type=fileUtils.typeFromUrl(childName);
|
||||
if (type.equalsIgnoreCase("picture")){//添加图片文件到图片列表
|
||||
imgUrls.add(baseUrl+childName);
|
||||
}
|
||||
FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory,fileKey);
|
||||
addNodes(appender, parentName, node);
|
||||
appender.put(childName, node);
|
||||
}
|
||||
executors.submit(new RarExtractorWorker(headersToBeExtracted, archive, filePath));
|
||||
fileUtils.setRedisImgUrls(fileKey,imgUrls);
|
||||
return new ObjectMapper().writeValueAsString(appender.get(""));
|
||||
} catch (RarException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void addNodes(Map<String, FileNode> appender, String parentName, FileNode node) {
|
||||
if (appender.containsKey(parentName)) {
|
||||
appender.get(parentName).getChildList().add(node);
|
||||
Collections.sort(appender.get(parentName).getChildList(), sortComparator);
|
||||
// appender.get(parentName).getChildList().sort((final FileNode h1, final FileNode h2) -> h1.getOriginName().compareTo(h2.getOriginName()));//排序
|
||||
}else { // 根节点
|
||||
FileNode nodeRoot = new FileNode(parentName, parentName, "", new ArrayList<>(), true);
|
||||
nodeRoot.getChildList().add(node);
|
||||
appender.put("", nodeRoot);
|
||||
appender.put(parentName, nodeRoot);
|
||||
}
|
||||
}
|
||||
|
||||
private List<FileHeader> sortedHeaders(List<FileHeader> headers) {
|
||||
List<FileHeader> sortedHeaders = new ArrayList<>();
|
||||
Map<Integer, FileHeader> mapHeaders = new TreeMap<>();
|
||||
headers.forEach(header -> mapHeaders.put(header.getFileNameW().length(), header));
|
||||
for (Map.Entry<Integer, FileHeader> entry : mapHeaders.entrySet()){
|
||||
for (FileHeader header : headers) {
|
||||
if (entry.getKey().intValue() == header.getFileNameW().length()) {
|
||||
sortedHeaders.add(header);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sortedHeaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取倒数第二个文件(夹)名
|
||||
* @param fullName
|
||||
* @param seperator
|
||||
* 压缩文件解压后,不同的压缩格式分隔符不一样zip是/,而rar是\
|
||||
* @param rootName
|
||||
* 根目录名:如果倒数第二个路径为空,那么赋值为rootName
|
||||
* @return
|
||||
*/
|
||||
private static String getLast2FileName(String fullName, String seperator, String rootName) {
|
||||
if (fullName.endsWith(seperator)) {
|
||||
fullName = fullName.substring(0, fullName.length()-1);
|
||||
}
|
||||
// 1.获取剩余部分
|
||||
int endIndex = fullName.lastIndexOf(seperator);
|
||||
String leftPath = fullName.substring(0, endIndex == -1 ? 0 : endIndex);
|
||||
if (null != leftPath && leftPath.length() > 1) {
|
||||
// 2.获取倒数第二个
|
||||
return getLastFileName(leftPath, seperator);
|
||||
}else {
|
||||
return rootName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一个文件(夹)的名字
|
||||
* @param fullName
|
||||
* @param seperator
|
||||
* 压缩文件解压后,不同的压缩格式分隔符不一样zip是/,而rar是\
|
||||
* @return
|
||||
*/
|
||||
private static String getLastFileName(String fullName, String seperator) {
|
||||
if (fullName.endsWith(seperator)) {
|
||||
fullName = fullName.substring(0, fullName.length()-1);
|
||||
}
|
||||
String newName = fullName;
|
||||
if (null != fullName && fullName.contains(seperator)) {
|
||||
newName = fullName.substring(fullName.lastIndexOf(seperator) + 1);
|
||||
}
|
||||
return newName;
|
||||
}
|
||||
|
||||
public static Comparator<FileNode> sortComparator = new Comparator<FileNode>() {
|
||||
Collator cmp = Collator.getInstance(Locale.US);
|
||||
@Override
|
||||
public int compare(FileNode o1, FileNode o2) {
|
||||
// 判断两个对比对象是否是开头包含数字,如果包含数字则获取数字并按数字真正大小进行排序
|
||||
BigDecimal num1,num2;
|
||||
if (null != (num1 = isStartNumber(o1))
|
||||
&& null != (num2 = isStartNumber(o2))) {
|
||||
return num1.subtract(num2).intValue();
|
||||
}
|
||||
CollationKey c1 = cmp.getCollationKey(o1.getOriginName());
|
||||
CollationKey c2 = cmp.getCollationKey(o2.getOriginName());
|
||||
return cmp.compare(c1.getSourceString(), c2.getSourceString());
|
||||
}
|
||||
};
|
||||
|
||||
private static BigDecimal isStartNumber(FileNode src) {
|
||||
Matcher matcher = pattern.matcher(src.getOriginName());
|
||||
if (matcher.find()) {
|
||||
return new BigDecimal(matcher.group());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件节点(区分文件上下级)
|
||||
*/
|
||||
public class FileNode{
|
||||
|
||||
private String originName;
|
||||
private String fileName;
|
||||
private String parentFileName;
|
||||
private boolean directory;
|
||||
private String fileKey;//用于图片预览时寻址
|
||||
private List<FileNode> childList;
|
||||
|
||||
public FileNode() {
|
||||
}
|
||||
|
||||
public FileNode(String originName, String fileName, String parentFileName, List<FileNode> childList, boolean directory) {
|
||||
this.originName = originName;
|
||||
this.fileName = fileName;
|
||||
this.parentFileName = parentFileName;
|
||||
this.childList = childList;
|
||||
this.directory = directory;
|
||||
}
|
||||
public FileNode(String originName, String fileName, String parentFileName, List<FileNode> childList, boolean directory,String fileKey) {
|
||||
this.originName = originName;
|
||||
this.fileName = fileName;
|
||||
this.parentFileName = parentFileName;
|
||||
this.childList = childList;
|
||||
this.directory = directory;
|
||||
this.fileKey=fileKey;
|
||||
}
|
||||
public String getFileKey() {
|
||||
return fileKey;
|
||||
}
|
||||
|
||||
public void setFileKey(String fileKey) {
|
||||
this.fileKey = fileKey;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
public String getParentFileName() {
|
||||
return parentFileName;
|
||||
}
|
||||
|
||||
public void setParentFileName(String parentFileName) {
|
||||
this.parentFileName = parentFileName;
|
||||
}
|
||||
|
||||
public List<FileNode> getChildList() {
|
||||
return childList;
|
||||
}
|
||||
|
||||
public void setChildList(List<FileNode> childList) {
|
||||
this.childList = childList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return new ObjectMapper().writeValueAsString(this);
|
||||
} catch (JsonProcessingException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public String getOriginName() {
|
||||
return originName;
|
||||
}
|
||||
|
||||
public void setOriginName(String originName) {
|
||||
this.originName = originName;
|
||||
}
|
||||
|
||||
public boolean isDirectory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
public void setDirectory(boolean directory) {
|
||||
this.directory = directory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip文件抽取线程
|
||||
*/
|
||||
class ZipExtractorWorker implements Runnable {
|
||||
|
||||
private List<Map<String, ZipArchiveEntry>> entriesToBeExtracted;
|
||||
private ZipFile zipFile;
|
||||
private String filePath;
|
||||
|
||||
public ZipExtractorWorker(List<Map<String, ZipArchiveEntry>> entriesToBeExtracted, ZipFile zipFile, String filePath) {
|
||||
this.entriesToBeExtracted = entriesToBeExtracted;
|
||||
this.zipFile = zipFile;
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("解析压缩文件开始《《《《《《《《《《《《《《《《《《《《《《《");
|
||||
for (Map<String, ZipArchiveEntry> entryMap : entriesToBeExtracted) {
|
||||
String childName = entryMap.keySet().iterator().next();
|
||||
ZipArchiveEntry entry = entryMap.values().iterator().next();
|
||||
try {
|
||||
extractZipFile(childName, zipFile.getInputStream(entry));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try {
|
||||
zipFile.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (new File(filePath).exists()) {
|
||||
new File(filePath).delete();
|
||||
}
|
||||
System.out.println("解析压缩文件结束《《《《《《《《《《《《《《《《《《《《《《《");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 读取压缩文件并写入到fileDir文件夹下
|
||||
* @param childName
|
||||
* @param zipFile
|
||||
*/
|
||||
private void extractZipFile(String childName, InputStream zipFile) {
|
||||
String outPath = fileDir + childName;
|
||||
try (OutputStream ot = new FileOutputStream(outPath)){
|
||||
byte[] inByte = new byte[1024];
|
||||
int len;
|
||||
while ((-1 != (len = zipFile.read(inByte)))){
|
||||
ot.write(inByte, 0, len);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rar文件抽取
|
||||
*/
|
||||
class RarExtractorWorker implements Runnable {
|
||||
private List<Map<String, FileHeader>> headersToBeExtracted;
|
||||
private Archive archive;
|
||||
/**
|
||||
* 用以删除源文件
|
||||
*/
|
||||
private String filePath;
|
||||
|
||||
public RarExtractorWorker(List<Map<String, FileHeader>> headersToBeExtracted, Archive archive, String filePath) {
|
||||
this.headersToBeExtracted = headersToBeExtracted;
|
||||
this.archive = archive;
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
System.out.println("解析压缩文件开始《《《《《《《《《《《《《《《《《《《《《《《");
|
||||
for (Map<String, FileHeader> entryMap : headersToBeExtracted) {
|
||||
String childName = entryMap.keySet().iterator().next();
|
||||
extractRarFile(childName, entryMap.values().iterator().next(), archive);
|
||||
}
|
||||
try {
|
||||
archive.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (new File(filePath).exists()) {
|
||||
new File(filePath).delete();
|
||||
}
|
||||
System.out.println("解析压缩文件结束《《《《《《《《《《《《《《《《《《《《《《《");
|
||||
}
|
||||
|
||||
/**
|
||||
* 抽取rar文件到指定目录下
|
||||
* @param childName
|
||||
* @param header
|
||||
* @param archive
|
||||
*/
|
||||
private void extractRarFile(String childName, FileHeader header, Archive archive) {
|
||||
String outPath = fileDir + childName;
|
||||
try(OutputStream ot = new FileOutputStream(outPath)) {
|
||||
archive.extractFile(header, ot);
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (RarException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user