Compare commits

...

4 Commits
md-ui ... io

16 changed files with 346 additions and 211 deletions

View File

@@ -1,5 +1,7 @@
[#ftl] [#ftl]
[#-- @implicitly included --] [#-- @implicitly included --]
[#-- @ftlvariable name="file" type="cn.keking.model.FileAttribute" --]
[#-- @ftlvariable name="fileName" type="java.lang.String" --]
[#-- @ftlvariable name="fileTree" type="java.lang.String" --] [#-- @ftlvariable name="fileTree" type="java.lang.String" --]
[#-- @ftlvariable name="baseUrl" type="java.lang.String" --] [#-- @ftlvariable name="baseUrl" type="java.lang.String" --]
[#-- @ftlvariable name="imgUrls" type="String" --] [#-- @ftlvariable name="imgUrls" type="String" --]

View File

@@ -1,7 +1,7 @@
package cn.keking.config; package cn.keking.config;
import cn.keking.service.cache.CacheService; import cn.keking.service.cache.CacheService;
import cn.keking.utils.FileUtils; import cn.keking.utils.KkFileUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
@@ -31,7 +31,7 @@ public class SchedulerCleanConfig {
public void clean() { public void clean() {
logger.info("Cache clean start"); logger.info("Cache clean start");
cacheService.cleanCache(); cacheService.cleanCache();
FileUtils.deleteDirectory(fileDir); KkFileUtils.deleteDirectory(fileDir);
logger.info("Cache clean end"); logger.info("Cache clean end");
} }
} }

View File

@@ -2,7 +2,7 @@ package cn.keking.service;
import cn.keking.config.ConfigConstants; import cn.keking.config.ConfigConstants;
import cn.keking.model.FileType; import cn.keking.model.FileType;
import cn.keking.utils.FileUtils; import cn.keking.utils.KkFileUtils;
import cn.keking.web.filter.BaseUrlFilter; import cn.keking.web.filter.BaseUrlFilter;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@@ -48,7 +48,7 @@ public class CompressFileReader {
String baseUrl = BaseUrlFilter.getBaseUrl(); String baseUrl = BaseUrlFilter.getBaseUrl();
String archiveFileName = fileHandlerService.getFileNameFromPath(filePath); String archiveFileName = fileHandlerService.getFileNameFromPath(filePath);
try { try {
ZipFile zipFile = new ZipFile(filePath, FileUtils.getFileEncode(filePath)); ZipFile zipFile = new ZipFile(filePath, KkFileUtils.getFileEncode(filePath));
Enumeration<ZipArchiveEntry> entries = zipFile.getEntries(); Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
// 排序 // 排序
entries = sortZipEntries(entries); entries = sortZipEntries(entries);
@@ -382,7 +382,7 @@ public class CompressFileReader {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
FileUtils.deleteFileByPath(filePath); KkFileUtils.deleteFileByPath(filePath);
} }
private void extractZipFile(String childName, InputStream zipFile) { private void extractZipFile(String childName, InputStream zipFile) {
@@ -439,7 +439,7 @@ public class CompressFileReader {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
FileUtils.deleteFileByPath(filePath); KkFileUtils.deleteFileByPath(filePath);
} }
} }
@@ -468,7 +468,7 @@ public class CompressFileReader {
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
FileUtils.deleteFileByPath(filePath); KkFileUtils.deleteFileByPath(filePath);
} }
private void extractRarFile(String childName, FileHeader header, Archive archive) { private void extractRarFile(String childName, FileHeader header, Archive archive) {

View File

@@ -4,7 +4,7 @@ import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute; import cn.keking.model.FileAttribute;
import cn.keking.model.FileType; import cn.keking.model.FileType;
import cn.keking.service.cache.CacheService; import cn.keking.service.cache.CacheService;
import cn.keking.utils.FileUtils; import cn.keking.utils.KkFileUtils;
import cn.keking.utils.WebUtils; import cn.keking.utils.WebUtils;
import com.aspose.cad.Color; import com.aspose.cad.Color;
import com.aspose.cad.fileformats.cad.CadDrawTypeMode; import com.aspose.cad.fileformats.cad.CadDrawTypeMode;
@@ -263,7 +263,7 @@ public class FileHandlerService {
if (StringUtils.hasText(fullFileName)) { if (StringUtils.hasText(fullFileName)) {
fileName = fullFileName; fileName = fullFileName;
type = FileType.typeFromFileName(fullFileName); type = FileType.typeFromFileName(fullFileName);
suffix = FileUtils.suffixFromFileName(fullFileName); suffix = KkFileUtils.suffixFromFileName(fullFileName);
} else { } else {
fileName = WebUtils.getFileNameFromURL(url); fileName = WebUtils.getFileNameFromURL(url);
type = FileType.typeFromUrl(url); type = FileType.typeFromUrl(url);

View File

@@ -17,6 +17,8 @@ public interface FilePreview {
String OFFICE_PICTURE_FILE_PREVIEW_PAGE = "officePicture"; String OFFICE_PICTURE_FILE_PREVIEW_PAGE = "officePicture";
String TXT_FILE_PREVIEW_PAGE = "txt"; String TXT_FILE_PREVIEW_PAGE = "txt";
String EXEL_FILE_PREVIEW_PAGE = "html"; String EXEL_FILE_PREVIEW_PAGE = "html";
String XML_FILE_PREVIEW_PAGE = "xml";
String MARKDOWN_FILE_PREVIEW_PAGE = "markdown";
String NOT_SUPPORTED_FILE_PAGE = "fileNotSupported"; String NOT_SUPPORTED_FILE_PAGE = "fileNotSupported";
String filePreviewHandle(String url, Model model, FileAttribute fileAttribute); String filePreviewHandle(String url, Model model, FileAttribute fileAttribute);

View File

@@ -5,8 +5,6 @@ import cn.keking.service.FilePreview;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import static cn.keking.service.impl.SimTextFilePreviewImpl.TEXT_TYPE;
/** /**
* @author kl (http://kailing.pub) * @author kl (http://kailing.pub)
* @since 2020/12/25 * @since 2020/12/25
@@ -23,7 +21,7 @@ public class MarkdownFilePreviewImpl implements FilePreview {
@Override @Override
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
model.addAttribute(TEXT_TYPE,"markdown"); simTextFilePreview.filePreviewHandle(url, model, fileAttribute);
return simTextFilePreview.filePreviewHandle(url, model, fileAttribute); return MARKDOWN_FILE_PREVIEW_PAGE;
} }
} }

View File

@@ -4,6 +4,7 @@ import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse; import cn.keking.model.ReturnResponse;
import cn.keking.service.FilePreview; import cn.keking.service.FilePreview;
import cn.keking.utils.DownloadUtils; import cn.keking.utils.DownloadUtils;
import cn.keking.utils.KkFileUtils;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.Model; import org.springframework.ui.Model;
@@ -11,7 +12,6 @@ import org.springframework.util.Base64Utils;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
/** /**
* Created by kl on 2018/1/17. * Created by kl on 2018/1/17.
@@ -20,9 +20,6 @@ import java.nio.charset.StandardCharsets;
@Service @Service
public class SimTextFilePreviewImpl implements FilePreview { public class SimTextFilePreviewImpl implements FilePreview {
public static final String TEXT_TYPE = "textType";
public static final String DEFAULT_TEXT_TYPE = "simText";
private final OtherFilePreviewImpl otherFilePreview; private final OtherFilePreviewImpl otherFilePreview;
public SimTextFilePreviewImpl(OtherFilePreviewImpl otherFilePreview) { public SimTextFilePreviewImpl(OtherFilePreviewImpl otherFilePreview) {
@@ -38,14 +35,12 @@ public class SimTextFilePreviewImpl implements FilePreview {
} }
try { try {
File originFile = new File(response.getContent()); File originFile = new File(response.getContent());
String xmlString = FileUtils.readFileToString(originFile, StandardCharsets.UTF_8); String charset = KkFileUtils.getFileEncode(originFile);
model.addAttribute("textData", Base64Utils.encodeToString(xmlString.getBytes(StandardCharsets.UTF_8))); String xmlString = FileUtils.readFileToString(originFile, charset);
model.addAttribute("textData", Base64Utils.encodeToString(xmlString.getBytes(charset)));
} catch (IOException e) { } catch (IOException e) {
return otherFilePreview.notSupportedFile(model, fileAttribute, e.getLocalizedMessage()); return otherFilePreview.notSupportedFile(model, fileAttribute, e.getLocalizedMessage());
} }
if (!model.containsAttribute(TEXT_TYPE)) {
model.addAttribute(TEXT_TYPE, DEFAULT_TEXT_TYPE);
}
return TXT_FILE_PREVIEW_PAGE; return TXT_FILE_PREVIEW_PAGE;
} }

View File

@@ -5,8 +5,6 @@ import cn.keking.service.FilePreview;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import static cn.keking.service.impl.SimTextFilePreviewImpl.TEXT_TYPE;
/** /**
* @author kl (http://kailing.pub) * @author kl (http://kailing.pub)
* @since 2020/12/25 * @since 2020/12/25
@@ -22,7 +20,7 @@ public class XmlFilePreviewImpl implements FilePreview {
@Override @Override
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) { public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
model.addAttribute(TEXT_TYPE,"xml"); simTextFilePreview.filePreviewHandle(url, model, fileAttribute);
return simTextFilePreview.filePreviewHandle(url, model, fileAttribute); return XML_FILE_PREVIEW_PAGE;
} }
} }

View File

@@ -2,17 +2,19 @@ package cn.keking.utils;
import cn.keking.config.ConfigConstants; import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute; import cn.keking.model.FileAttribute;
import cn.keking.model.FileType;
import cn.keking.model.ReturnResponse; import cn.keking.model.ReturnResponse;
import io.mola.galimatias.GalimatiasParseException; import io.mola.galimatias.GalimatiasParseException;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.UUID; import java.util.UUID;
import static cn.keking.utils.KkFileUtils.isFtpUrl;
import static cn.keking.utils.KkFileUtils.isHttpUrl;
/** /**
* @author yudian-it * @author yudian-it
*/ */
@@ -31,42 +33,26 @@ public class DownloadUtils {
*/ */
public static ReturnResponse<String> downLoad(FileAttribute fileAttribute, String fileName) { public static ReturnResponse<String> downLoad(FileAttribute fileAttribute, String fileName) {
String urlStr = fileAttribute.getUrl(); String urlStr = fileAttribute.getUrl();
String type = fileAttribute.getSuffix();
ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", ""); ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", "");
UUID uuid = UUID.randomUUID(); String realPath = DownloadUtils.getRelFilePath(fileName, fileAttribute);
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()) {
logger.error("创建目录【{}】失败,可能是权限不够,请检查", fileDir);
}
try { try {
URL url = new URL(urlStr); URL url = WebUtils.normalizedURL(urlStr);
if (url.getProtocol() != null && (url.getProtocol().toLowerCase().startsWith("file") || url.getProtocol().toLowerCase().startsWith("http"))) { if (isHttpUrl(url)) {
byte[] bytes = getBytesFromUrl(urlStr); File realFile = new File(realPath);
OutputStream os = new FileOutputStream(realPath); FileUtils.copyURLToFile(url, realFile);
saveBytesToOutStream(bytes, os); } else if (isFtpUrl(url)) {
} else if (url.getProtocol() != null && "ftp".equalsIgnoreCase(url.getProtocol())) {
String ftpUsername = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_USERNAME); String ftpUsername = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_USERNAME);
String ftpPassword = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_PASSWORD); String ftpPassword = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_PASSWORD);
String ftpControlEncoding = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_CONTROL_ENCODING); String ftpControlEncoding = WebUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_CONTROL_ENCODING);
FtpUtils.download(fileAttribute.getUrl(), realPath, ftpUsername, ftpPassword, ftpControlEncoding); FtpUtils.download(fileAttribute.getUrl(), realPath, ftpUsername, ftpPassword, ftpControlEncoding);
} else { } else {
response.setCode(1); response.setCode(1);
response.setContent(null);
response.setMsg("url不能识别url" + urlStr); response.setMsg("url不能识别url" + urlStr);
} }
response.setContent(realPath); response.setContent(realPath);
response.setMsg(fileName); response.setMsg(fileName);
if (FileType.simText.equals(fileAttribute.getType())) {
convertTextPlainFileCharsetToUtf8(realPath);
}
return response; return response;
} catch (IOException e) { } catch (IOException | GalimatiasParseException e) {
logger.error("文件下载失败url{}", urlStr, e); logger.error("文件下载失败url{}", urlStr, e);
response.setCode(1); response.setCode(1);
response.setContent(null); response.setContent(null);
@@ -79,82 +65,27 @@ public class DownloadUtils {
} }
} }
public static byte[] getBytesFromUrl(String urlStr) throws IOException {
InputStream is = getInputStreamFromUrl(urlStr);
if (is == null) {
is = getInputStreamFromUrl(urlStr);
if (is == null) {
logger.error("文件下载异常url{}", urlStr);
throw new IOException("文件下载异常url" + urlStr);
}
}
return getBytesFromStream(is);
}
public static void saveBytesToOutStream(byte[] b, OutputStream os) throws IOException {
os.write(b);
os.close();
}
private static InputStream getInputStreamFromUrl(String urlStr) {
try {
URL url = io.mola.galimatias.URL.parse(urlStr).toJavaURL();
URLConnection connection = url.openConnection();
if (connection instanceof HttpURLConnection) {
connection.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
}
return connection.getInputStream();
} catch (IOException | GalimatiasParseException e) {
logger.warn("连接url异常url{}", urlStr);
return null;
}
}
private static byte[] getBytesFromStream(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
baos.write(buffer, 0, len);
}
byte[] b = baos.toByteArray();
is.close();
baos.close();
return b;
}
/** /**
* 转换文本文件编码为utf8 * 获取真实文件绝对路径
* 探测源文件编码,探测到编码切不为utf8则进行转码
* *
* @param filePath 文件路径 * @param fileName 文件
* @return 文件路径
*/ */
private static void convertTextPlainFileCharsetToUtf8(String filePath) throws IOException { private static String getRelFilePath(String fileName, FileAttribute fileAttribute) {
File sourceFile = new File(filePath); String type = fileAttribute.getSuffix();
if (sourceFile.exists() && sourceFile.isFile() && sourceFile.canRead()) { if (null == fileName) {
String encoding = FileUtils.getFileEncode(filePath); UUID uuid = UUID.randomUUID();
if (!FileUtils.DEFAULT_FILE_ENCODING.equals(encoding)) { fileName = uuid + "." + type;
// 不为utf8,进行转码 } else { // 文件后缀不一致时以type为准(针对simText【将类txt文件转为txt】)
File tmpUtf8File = new File(filePath + ".utf8"); fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type);
Writer writer = new OutputStreamWriter(new FileOutputStream(tmpUtf8File), StandardCharsets.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();
// 删除源文件
if (!sourceFile.delete()) {
logger.error("源文件【{}】删除失败,请检查文件目录权限!", filePath);
}
// 重命名
if (tmpUtf8File.renameTo(sourceFile)) {
logger.error("临时文件【{}】重命名失败,请检查文件路径权限!", tmpUtf8File.getPath());
}
}
} }
String realPath = fileDir + fileName;
File dirFile = new File(fileDir);
if (!dirFile.exists() && !dirFile.mkdirs()) {
logger.error("创建目录【{}】失败,可能是权限不够,请检查", fileDir);
}
return realPath;
} }
} }

View File

@@ -6,19 +6,39 @@ import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL;
import java.util.Objects; import java.util.Objects;
public class FileUtils { public class KkFileUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(FileUtils.class); private static final Logger LOGGER = LoggerFactory.getLogger(KkFileUtils.class);
public static final String DEFAULT_FILE_ENCODING = "UTF-8"; public static final String DEFAULT_FILE_ENCODING = "UTF-8";
/**
* 判断url是否是http资源
*
* @param url url
* @return 是否http
*/
public static boolean isHttpUrl(URL url) {
return url.getProtocol().toLowerCase().startsWith("file") || url.getProtocol().toLowerCase().startsWith("http");
}
/**
* 判断url是否是ftp资源
*
* @param url url
* @return 是否ftp
*/
public static boolean isFtpUrl(URL url) {
return "ftp".equalsIgnoreCase(url.getProtocol());
}
/** /**
* 删除单个文件 * 删除单个文件
* *
* @param fileName * @param fileName 要删除的文件的文件名
* 要删除的文件的文件名
* @return 单个文件删除成功返回true否则返回false * @return 单个文件删除成功返回true否则返回false
*/ */
public static boolean deleteFileByName(String fileName) { public static boolean deleteFileByName(String fileName) {
@@ -39,17 +59,26 @@ public class FileUtils {
} }
/** /**
* 判断文件编码格式 * 检测文件编码格式
* *
* @param filePath 绝对路径 * @param filePath 绝对路径
* @return 编码格式 * @return 编码格式
*/ */
public static String getFileEncode(String filePath) { public static String getFileEncode(String filePath) {
File file = new File(filePath); return getFileEncode(new File(filePath));
}
/**
* 检测文件编码格式
*
* @param file 检测的文件
* @return 编码格式
*/
public static String getFileEncode(File file) {
CharsetPrinter cp = new CharsetPrinter(); CharsetPrinter cp = new CharsetPrinter();
try { try {
String encoding = cp.guessEncoding(file); String encoding = cp.guessEncoding(file);
LOGGER.info("检测到文件【{}】编码: {}", filePath, encoding); LOGGER.info("检测到文件【{}】编码: {}", file.getAbsolutePath(), encoding);
return encoding; return encoding;
} catch (IOException e) { } catch (IOException e) {
LOGGER.warn("文件编码获取失败采用默认的编码格式UTF-8", e); LOGGER.warn("文件编码获取失败采用默认的编码格式UTF-8", e);
@@ -59,6 +88,7 @@ public class FileUtils {
/** /**
* 通过文件名获取文件后缀 * 通过文件名获取文件后缀
*
* @param fileName 文件名称 * @param fileName 文件名称
* @return 文件后缀 * @return 文件后缀
*/ */
@@ -82,8 +112,7 @@ public class FileUtils {
/** /**
* 删除目录及目录下的文件 * 删除目录及目录下的文件
* *
* @param dir * @param dir 要删除的目录的文件路径
* 要删除的目录的文件路径
* @return 目录删除成功返回true否则返回false * @return 目录删除成功返回true否则返回false
*/ */
public static boolean deleteDirectory(String dir) { public static boolean deleteDirectory(String dir) {
@@ -103,13 +132,13 @@ public class FileUtils {
for (int i = 0; i < Objects.requireNonNull(files).length; i++) { for (int i = 0; i < Objects.requireNonNull(files).length; i++) {
// 删除子文件 // 删除子文件
if (files[i].isFile()) { if (files[i].isFile()) {
flag = FileUtils.deleteFileByName(files[i].getAbsolutePath()); flag = KkFileUtils.deleteFileByName(files[i].getAbsolutePath());
if (!flag) { if (!flag) {
break; break;
} }
} else if (files[i].isDirectory()) { } else if (files[i].isDirectory()) {
// 删除子目录 // 删除子目录
flag = FileUtils.deleteDirectory(files[i].getAbsolutePath()); flag = KkFileUtils.deleteDirectory(files[i].getAbsolutePath());
if (!flag) { if (!flag) {
break; break;
} }

View File

@@ -1,5 +1,9 @@
package cn.keking.utils; package cn.keking.utils;
import io.mola.galimatias.GalimatiasParseException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -8,6 +12,16 @@ import java.util.Map;
* create : 2020-12-27 1:30 上午 * create : 2020-12-27 1:30 上午
**/ **/
public class WebUtils { public class WebUtils {
/**
* 获取标准的URL
* @param urlStr url
* @return 标准的URL
*/
public static URL normalizedURL(String urlStr) throws GalimatiasParseException, MalformedURLException {
return io.mola.galimatias.URL.parse(urlStr).toJavaURL();
}
/** /**
* 获取url中的参数 * 获取url中的参数
* *
@@ -81,6 +95,6 @@ public class WebUtils {
public static String suffixFromUrl(String url) { public static String suffixFromUrl(String url) {
String nonPramStr = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length()); String nonPramStr = url.substring(0, url.contains("?") ? url.indexOf("?") : url.length());
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1); String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
return FileUtils.suffixFromFileName(fileName); return KkFileUtils.suffixFromFileName(fileName);
} }
} }

View File

@@ -6,8 +6,10 @@ import cn.keking.service.FilePreviewFactory;
import cn.keking.service.cache.CacheService; import cn.keking.service.cache.CacheService;
import cn.keking.service.impl.OtherFilePreviewImpl; import cn.keking.service.impl.OtherFilePreviewImpl;
import cn.keking.utils.DownloadUtils;
import cn.keking.service.FileHandlerService; import cn.keking.service.FileHandlerService;
import cn.keking.utils.WebUtils;
import io.mola.galimatias.GalimatiasParseException;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
@@ -21,6 +23,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.*; import java.io.*;
import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -57,6 +60,7 @@ public class OnlinePreviewController {
return otherFilePreview.notSupportedFile(model, errorMsg); return otherFilePreview.notSupportedFile(model, errorMsg);
} }
FileAttribute fileAttribute = fileHandlerService.getFileAttribute(fileUrl, req); FileAttribute fileAttribute = fileHandlerService.getFileAttribute(fileUrl, req);
model.addAttribute("file", fileAttribute);
FilePreview filePreview = previewFactory.get(fileAttribute); FilePreview filePreview = previewFactory.get(fileAttribute);
logger.info("预览文件url{}previewType{}", fileUrl, fileAttribute.getType()); logger.info("预览文件url{}previewType{}", fileUrl, fileAttribute.getType());
return filePreview.filePreviewHandle(fileUrl, model, fileAttribute); return filePreview.filePreviewHandle(fileUrl, model, fileAttribute);
@@ -98,9 +102,10 @@ public class OnlinePreviewController {
public void getCorsFile(String urlPath, HttpServletResponse response) { public void getCorsFile(String urlPath, HttpServletResponse response) {
logger.info("下载跨域pdf文件url{}", urlPath); logger.info("下载跨域pdf文件url{}", urlPath);
try { try {
byte[] bytes = DownloadUtils.getBytesFromUrl(urlPath); URL url = WebUtils.normalizedURL(urlPath);
DownloadUtils.saveBytesToOutStream(bytes, response.getOutputStream()); byte[] bytes = IOUtils.toByteArray(url);
} catch (IOException e) { IOUtils.write(bytes, response.getOutputStream());
} catch (IOException | GalimatiasParseException e) {
logger.error("下载跨域pdf文件异常url{}", urlPath, e); logger.error("下载跨域pdf文件异常url{}", urlPath, e);
} }
} }

View File

@@ -61,7 +61,7 @@
<div style="padding: 10px"> <div style="padding: 10px">
<form enctype="multipart/form-data" id="fileUpload"> <form enctype="multipart/form-data" id="fileUpload">
<input type="file" name="file"/> <input type="file" name="file"/>
<input type="button" id="btnubmit" value=" "/> <input type="button" id="btnSubmit" value=" "/>
</form> </form>
</div> </div>
<div> <div>

View File

@@ -0,0 +1,118 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<title>普通文本预览</title>
</head>
<body>
<input hidden id="textData" value="${textData}"/>
<div class="container">
<div class="panel panel-default">
<div id="markdown_btn" class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
${file.name}
</a>
</h4>
</div>
<div id="text_btn" class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
${file.name}
</a>
</h4>
</div>
<div class="panel-body">
<div id="markdown"></div>
</div>
</div>
</div>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
<script src="js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script src="js/jquery.form.min.js" type="text/javascript"></script>
<script src="bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="js/watermark.js" type="text/javascript"></script>
<script src="js/marked.min.js" type="text/javascript"></script>
<script src="js/base64.min.js" type="text/javascript"></script>
<script>
/**
* 初始化
*/
window.onload = function () {
$("#markdown_btn").hide()
initWaterMark();
loadMarkdown();
}
/**
* 初始化水印
*/
function initWaterMark() {
let watermarkTxt = '${watermarkTxt}';
if (watermarkTxt !== '') {
watermark.init({
watermark_txt: '${watermarkTxt}',
watermark_x: 0,
watermark_y: 0,
watermark_rows: 0,
watermark_cols: 0,
watermark_x_space: ${watermarkXSpace},
watermark_y_space: ${watermarkYSpace},
watermark_font: '${watermarkFont}',
watermark_fontsize: '${watermarkFontsize}',
watermark_color: '${watermarkColor}',
watermark_alpha: ${watermarkAlpha},
watermark_width: ${watermarkWidth},
watermark_height: ${watermarkHeight},
watermark_angle: ${watermarkAngle},
});
}
}
/**
* 加载markdown
*/
function loadMarkdown() {
var textData = Base64.decode($("#textData").val())
window.textPreData = "<pre style='background-color: #FFFFFF;border:none'>" + textData + "</pre>";
window.textMarkdownData = marked(textData);
$("#markdown").html(window.textMarkdownData);
}
$(function () {
$("#markdown_btn").click(function () {
$("#markdown").html(window.textMarkdownData);
$("#text_btn").show()
$("#markdown_btn").hide()
});
$("#text_btn").click(function () {
$("#markdown_btn").show()
$("#text_btn").hide();
$("#markdown").html(window.textPreData);
});
});
</script>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
</style>
</body>
</html>

View File

@@ -6,32 +6,29 @@
<title>普通文本预览</title> <title>普通文本预览</title>
</head> </head>
<body> <body>
<input hidden id="textType" value="${textType}"/>
<input hidden id="textData" value="${textData}"/> <input hidden id="textData" value="${textData}"/>
<div class="container"> <div class="container">
<#if textType?? && textType == "markdown"> <div class="panel panel-default">
<p> <div class="panel-heading">
<button id="markdown_btn" type="button" class="btn btn-primary">切换markdown</button> <h4 class="panel-title">
<button id="text_btn" type="button" class="btn btn-primary">切换text</button> <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
</p> ${file.name}
<div id="markdown" style="padding: 18px;"></div> </a>
<#elseif textType?? && textType == "xml" > </h4>
<div id="xml" style="padding: 18px;"></div> </div>
<#else> <div class="panel-body">
<div id="text"></div> <div id="text"></div>
</#if> </div>
</div>
</div> </div>
<link rel="stylesheet" href="css/xmlTreeViewer.css"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
<script src="js/jquery-3.0.0.min.js" type="text/javascript"></script> <script src="js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script src="js/jquery.form.min.js" type="text/javascript"></script> <script src="js/jquery.form.min.js" type="text/javascript"></script>
<script src="bootstrap/js/bootstrap.min.js" type="text/javascript"></script> <script src="bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="js/watermark.js" type="text/javascript"></script> <script src="js/watermark.js" type="text/javascript"></script>
<script src="js/marked.min.js" type="text/javascript"></script>
<script src="js/xmlTreeViewer.js" type="text/javascript"></script>
<script src="js/base64.min.js" type="text/javascript"></script> <script src="js/base64.min.js" type="text/javascript"></script>
<script> <script>
@@ -39,12 +36,8 @@
* 初始化 * 初始化
*/ */
window.onload = function () { window.onload = function () {
$("#markdown_btn").hide()
initWaterMark(); initWaterMark();
fetchData();
loadText(); loadText();
loadXmlData()
loadMarkdown();
} }
/** /**
@@ -72,56 +65,16 @@
} }
} }
/**
* 获取文本数据
*/
function fetchData() {
window.textData = Base64.decode($("#textData").val())
window.textPreData = "<pre>" + window.textData + "</pre>";
}
/** /**
*加载普通文本 *加载普通文本
*/ */
function loadText() { function loadText() {
$("#text").html(window.textPreData); var textData = Base64.decode($("#textData").val())
var textPreData = "<pre style='background-color: #FFFFFF;border:none'>" + textData + "</pre>";
$("#text").html(textPreData);
} }
/**
* 加载markdown
*/
function loadMarkdown() {
if ($("#textType").val() === "markdown") {
window.textMarkdownData = marked(window.textData);
$("#markdown").html(window.textMarkdownData);
}
}
/**
* 加载xml数据
*/
function loadXmlData() {
if ($("#textType").val() === "xml") {
var xmlNode = xmlTreeViewer.parseXML(window.textData);
var retNode = xmlTreeViewer.getXMLViewerNode(xmlNode.xml);
$("#xml").html(retNode);
}
}
$(function () {
$("#markdown_btn").click(function () {
$("#markdown").html(window.textMarkdownData);
$("#text_btn").show()
$("#markdown_btn").hide()
});
$("#text_btn").click(function () {
$("#markdown_btn").show()
$("#text_btn").hide();
$("#markdown").html(window.textPreData);
});
});
</script> </script>
<style> <style>
* { * {
@@ -134,13 +87,6 @@
width: 100%; width: 100%;
} }
#markdown, #xml {
height: 97%;
max-height: 97%;
border: 1px solid #ece7e7;
overflow-y: scroll;
width: 100%;
}
</style> </style>
</body> </body>

View File

@@ -0,0 +1,97 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<title>普通文本预览</title>
</head>
<body>
<input hidden id="textData" value="${textData}"/>
<div class="container">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
${file.name}
</a>
</h4>
</div>
<div class="panel-body">
<div id="xml"></div>
</div>
</div>
</div>
<link rel="stylesheet" href="css/xmlTreeViewer.css"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
<script src="js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script src="js/jquery.form.min.js" type="text/javascript"></script>
<script src="bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="js/watermark.js" type="text/javascript"></script>
<script src="js/marked.min.js" type="text/javascript"></script>
<script src="js/xmlTreeViewer.js" type="text/javascript"></script>
<script src="js/base64.min.js" type="text/javascript"></script>
<script>
/**
* 初始化
*/
window.onload = function () {
initWaterMark();
loadXmlData()
}
/**
* 初始化水印
*/
function initWaterMark() {
let watermarkTxt = '${watermarkTxt}';
if (watermarkTxt !== '') {
watermark.init({
watermark_txt: '${watermarkTxt}',
watermark_x: 0,
watermark_y: 0,
watermark_rows: 0,
watermark_cols: 0,
watermark_x_space: ${watermarkXSpace},
watermark_y_space: ${watermarkYSpace},
watermark_font: '${watermarkFont}',
watermark_fontsize: '${watermarkFontsize}',
watermark_color: '${watermarkColor}',
watermark_alpha: ${watermarkAlpha},
watermark_width: ${watermarkWidth},
watermark_height: ${watermarkHeight},
watermark_angle: ${watermarkAngle},
});
}
}
/**
* 加载xml数据
*/
function loadXmlData() {
var textData = Base64.decode($("#textData").val())
var xmlNode = xmlTreeViewer.parseXML(textData);
var retNode = xmlTreeViewer.getXMLViewerNode(xmlNode.xml);
$("#xml").html(retNode);
}
</script>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
</style>
</body>
</html>