Compare commits

..

19 Commits
log ... jodd

Author SHA1 Message Date
chenkailing
27ae58a0f4 加回 apache-commons-io 包依赖,office组件中有依赖,后续再统一吧 2021-01-09 17:07:15 +08:00
chenkailing
4d83674806 移除 apache-commons-io 包依赖,采用jodd的io工具替代 2021-01-09 15:38:21 +08:00
kl
12c85c60c7 XML文件预览支持切换纯文本模式 2020-12-31 13:28:25 +08:00
kl
4747ee93b2 修复类文本类型HTML文件预览的bug 2020-12-29 18:37:50 +08:00
kl
5ec53c4b33 指定Base64转码采用Apache Commons-code中的实现,修复base64部分jdk版本下出现的异常 2020-12-29 18:32:24 +08:00
kl
ee7f7f50cc 修复大小写文件类型后缀没通用匹配的问题 2020-12-29 09:29:16 +08:00
chenkailing
92869e8d6c 文本文件编码默认UTF-8输出到页面 2020-12-28 23:56:38 +08:00
kl
c66dda239f 采用apache-common-io包简化所有的文件下载io操作 2020-12-28 18:31:12 +08:00
kl
e927760c40 调整多图连续预览上下翻图的UI 2020-12-28 16:45:11 +08:00
kl
8783f9059a 修复压缩包内多图连续预览的bug 2020-12-28 16:45:11 +08:00
kl
12e1239267 前端模板抽象出通用的header,将水印等初始化内容挪到通用header里 2020-12-28 16:45:11 +08:00
kl
7c963193ef 更新simTxT文件预览UI风格 2020-12-28 14:54:42 +08:00
kl
bce9a624d7 更新XML文件预览UI风格,调整类文本预览架构,更方便扩展 2020-12-28 14:54:42 +08:00
kl
dac3606b4e 更新markdown文件预览UI风格 2020-12-28 14:54:42 +08:00
kl
eb00385d76 更新index接入演示界面UI风格 2020-12-28 13:36:40 +08:00
kl
986f562266 引入galimatias,解决不规范文件名导致文件下载异常 2020-12-28 11:43:27 +08:00
kl
11d0441ed4 加回漏掉的pdfjs 2020-12-28 11:22:59 +08:00
kl
ef46e2c51e 增强url base64解码失败时的提示信息 2020-12-28 11:22:59 +08:00
kl
0a3c03f18b 修复发行包运行时找不到日志目录的问题 2020-12-28 11:22:59 +08:00
27 changed files with 504 additions and 652 deletions

View File

@@ -56,12 +56,6 @@
<groupId>cn.keking</groupId> <groupId>cn.keking</groupId>
<artifactId>office-plugin</artifactId> <artifactId>office-plugin</artifactId>
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
@@ -105,11 +99,6 @@
<artifactId>fr.opensagres.xdocreport.document</artifactId> <artifactId>fr.opensagres.xdocreport.document</artifactId>
<version>1.0.5</version> <version>1.0.5</version>
</dependency> </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- 解压(apache) --> <!-- 解压(apache) -->
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
@@ -201,6 +190,12 @@
<scope>system</scope> <scope>system</scope>
<systemPath>${basedir}/lib/cpdetector-1.04.jar</systemPath> <systemPath>${basedir}/lib/cpdetector-1.04.jar</systemPath>
</dependency> </dependency>
<!-- url 规范化 -->
<dependency>
<groupId>io.mola.galimatias</groupId>
<artifactId>galimatias</artifactId>
<version>0.2.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
<resources> <resources>

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

@@ -24,7 +24,7 @@ public enum FileType {
cad("cadFilePreviewImpl"); cad("cadFilePreviewImpl");
private static final String[] OFFICE_TYPES = {"docx", "doc", "xls", "xlsx", "ppt", "pptx"}; private static final String[] OFFICE_TYPES = {"docx", "doc", "xls", "xlsx", "ppt", "pptx"};
private static final String[] PICTURE_TYPES = {"jpg", "jpeg", "png", "gif", "bmp", "ico", "RAW"}; private static final String[] PICTURE_TYPES = {"jpg", "jpeg", "png", "gif", "bmp", "ico", "raw"};
private static final String[] ARCHIVE_TYPES = {"rar", "zip", "jar", "7-zip", "tar", "gzip", "7z"}; private static final String[] ARCHIVE_TYPES = {"rar", "zip", "jar", "7-zip", "tar", "gzip", "7z"};
private static final String[] SSIM_TEXT_TYPES = ConfigConstants.getSimText(); private static final String[] SSIM_TEXT_TYPES = ConfigConstants.getSimText();
private static final String[] MEDIA_TYPES = ConfigConstants.getMedia(); private static final String[] MEDIA_TYPES = ConfigConstants.getMedia();
@@ -71,7 +71,8 @@ public enum FileType {
public static FileType typeFromFileName(String fileName) { public static FileType typeFromFileName(String fileName) {
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1); String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
return FileType.to(fileType); String lowerCaseFileType = fileType.toLowerCase();
return FileType.to(lowerCaseFileType);
} }
private final String instanceName; private final String instanceName;

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);
@@ -275,7 +275,7 @@ public class FileHandlerService {
attribute.setUrl(url); attribute.setUrl(url);
if (req != null) { if (req != null) {
String officePreviewType = req.getParameter("officePreviewType"); String officePreviewType = req.getParameter("officePreviewType");
String fileKey = req.getParameter("fileKey"); String fileKey = WebUtils.getUrlParameterReg(url,"fileKey");
if (StringUtils.hasText(officePreviewType)) { if (StringUtils.hasText(officePreviewType)) {
attribute.setOfficePreviewType(officePreviewType); attribute.setOfficePreviewType(officePreviewType);
} }

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,14 +4,14 @@ 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 org.apache.commons.io.FileUtils; import cn.keking.utils.KkFileUtils;
import jodd.io.FileUtil;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.Model; import org.springframework.ui.Model;
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 fileData = FileUtil.readString(originFile, charset);
model.addAttribute("textData", Base64.encodeBase64String(fileData.getBytes()));
} 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,16 +2,20 @@ 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 jodd.io.FileUtil;
import jodd.io.NetUtil;
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
*/ */
@@ -30,42 +34,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); NetUtil.downloadFile(url.toString(),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);
@@ -78,82 +66,27 @@ public class DownloadUtils {
} }
} }
public static byte[] getBytesFromUrl(String urlStr) throws IOException {
InputStream is = getInputStreamFromUrl(urlStr);
if (is == null) {
// urlStr = URLUtil.normalize(urlStr, true, true);
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 = new URL(urlStr);
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 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,13 +6,16 @@ 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 fr.opensagres.xdocreport.core.io.IOUtils;
import io.mola.galimatias.GalimatiasParseException;
import jodd.io.NetUtil;
import org.apache.commons.codec.binary.Base64;
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;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
@@ -21,6 +24,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;
@@ -51,12 +55,13 @@ public class OnlinePreviewController {
public String onlinePreview(String url, Model model, HttpServletRequest req) { public String onlinePreview(String url, Model model, HttpServletRequest req) {
String fileUrl; String fileUrl;
try { try {
fileUrl = new String(Base64Utils.decodeFromString(url)); fileUrl = new String(Base64.decodeBase64(url));
} catch (Exception ex) { } catch (Exception ex) {
String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url"); String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "url");
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);
@@ -66,7 +71,7 @@ public class OnlinePreviewController {
public String picturesPreview(String urls, Model model, HttpServletRequest req) throws UnsupportedEncodingException { public String picturesPreview(String urls, Model model, HttpServletRequest req) throws UnsupportedEncodingException {
String fileUrls; String fileUrls;
try { try {
fileUrls = new String(Base64Utils.decodeFromString(urls)); fileUrls = new String(Base64.decodeBase64(urls));
} catch (Exception ex) { } catch (Exception ex) {
String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "urls"); String errorMsg = String.format(BASE64_DECODE_ERROR_MSG, "urls");
return otherFilePreview.notSupportedFile(model, errorMsg); return otherFilePreview.notSupportedFile(model, errorMsg);
@@ -79,7 +84,7 @@ public class OnlinePreviewController {
String currentUrl = req.getParameter("currentUrl"); String currentUrl = req.getParameter("currentUrl");
if (StringUtils.hasText(currentUrl)) { if (StringUtils.hasText(currentUrl)) {
String decodedCurrentUrl = new String(Base64Utils.decodeFromString(currentUrl)); String decodedCurrentUrl = new String(Base64.decodeBase64(currentUrl));
model.addAttribute("currentUrl", decodedCurrentUrl); model.addAttribute("currentUrl", decodedCurrentUrl);
} else { } else {
model.addAttribute("currentUrl", imgUrls.get(0)); model.addAttribute("currentUrl", imgUrls.get(0));
@@ -98,9 +103,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 = NetUtil.downloadBytes(url.toString());
} 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

@@ -0,0 +1,49 @@
<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/base64.min.js" type="text/javascript"></script>
<script>
/**
* 初始化水印
*/
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},
});
}
}
</script>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
</style>

View File

@@ -5,15 +5,8 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<link href="css/zTreeStyle.css" rel="stylesheet" type="text/css"> <link href="css/zTreeStyle.css" rel="stylesheet" type="text/css">
<#include "*/commonHeader.ftl">
<style type="text/css"> <style type="text/css">
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
body { body {
background-color: #404040; background-color: #404040;
} }
@@ -32,10 +25,7 @@
<div class="zTreeDemoBackground left"> <div class="zTreeDemoBackground left">
<ul id="treeDemo" class="ztree"></ul> <ul id="treeDemo" class="ztree"></ul>
</div> </div>
<script src="js/watermark.js" type="text/javascript"></script>
<script type="text/javascript" src="js/jquery-3.0.0.min.js"></script>
<script type="text/javascript" src="js/jquery.ztree.core.js"></script> <script type="text/javascript" src="js/jquery.ztree.core.js"></script>
<script type="text/javascript" src="js/base64.min.js" ></script>
<script type="text/javascript"> <script type="text/javascript">
const data = JSON.parse('${fileTree}'); const data = JSON.parse('${fileTree}');
@@ -87,25 +77,7 @@
/*初始化水印*/ /*初始化水印*/
window.onload = function() { window.onload = function() {
var watermarkTxt = '${watermarkTxt}'; initWaterMark();
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},
});
}
} }
/** /**

View File

@@ -32,7 +32,7 @@
<div class="container"> <div class="container">
<img src="images/sorry.jpg" /> <img src="images/sorry.jpg" />
<span> <span>
该文件类型(${fileType})系统暂时不支持在线预览,<b>说明</b> 该文件类型(${file.suffix})系统暂时不支持在线预览,<b>说明</b>
<p style="color: red;">${msg}</p> <p style="color: red;">${msg}</p>
有任何疑问,请加&nbsp;<a href="https://jq.qq.com/?_wv=1027&k=5c0UAtu">官方QQ群613025121</a>&nbsp;咨询 有任何疑问,请加&nbsp;<a href="https://jq.qq.com/?_wv=1027&k=5c0UAtu">官方QQ群613025121</a>&nbsp;咨询
</span> </span>

View File

@@ -3,18 +3,10 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>多媒体文件预览</title> <title>多媒体文件预览</title>
<script src="js/flv.min.js"type="text/javascript"></script> <script src="js/flv.min.js" type="text/javascript"></script>
<script src="js/watermark.js" type="text/javascript"></script> <#include "*/commonHeader.ftl">
</head> </head>
<style> <style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
body { body {
background-color: #404040; background-color: #404040;
} }
@@ -40,25 +32,7 @@
} }
/*初始化水印*/ /*初始化水印*/
window.onload = function() { window.onload = function() {
var watermarkTxt = '${watermarkTxt}'; initWaterMark();
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},
});
}
} }
</script> </script>
</body> </body>

View File

@@ -4,21 +4,11 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<style type="text/css"> <#include "*/commonHeader.ftl">
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
</style>
</head> </head>
<body> <body>
<iframe src="${pdfUrl}" width="100%" frameborder="0"></iframe> <iframe src="${pdfUrl}" width="100%" frameborder="0"></iframe>
</body> </body>
<script src="js/watermark.js" type="text/javascript"></script>
<script type="text/javascript"> <script type="text/javascript">
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight-10; document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight-10;
/** /**
@@ -30,25 +20,7 @@
} }
/*初始化水印*/ /*初始化水印*/
window.onload = function() { window.onload = function() {
var watermarkTxt = '${watermarkTxt}'; initWaterMark();
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},
});
}
} }
</script> </script>
</html> </html>

View File

@@ -2,51 +2,49 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"/>
<title>kkFileView演示首页</title> <title>kkFileView演示首页</title>
<link rel="stylesheet" href="css/viewer.min.css" /> <link rel="stylesheet" href="css/viewer.min.css"/>
<link rel="stylesheet" href="css/loading.css" /> <link rel="stylesheet" href="css/loading.css"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" /> <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
<link rel="stylesheet" href="bootstrap-table/bootstrap-table.min.css" /> <link rel="stylesheet" href="bootstrap-table/bootstrap-table.min.css"/>
<link rel="stylesheet" href="gitalk/gitalk.css" /> <link rel="stylesheet" href="gitalk/gitalk.css"/>
<script type="text/javascript" src="js/jquery-3.0.0.min.js"></script> <script type="text/javascript" src="js/jquery-3.0.0.min.js"></script>
<script type="text/javascript" src="js/jquery.form.min.js"></script> <script type="text/javascript" src="js/jquery.form.min.js"></script>
<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script> <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="bootstrap-table/bootstrap-table.min.js"></script> <script type="text/javascript" src="bootstrap-table/bootstrap-table.min.js"></script>
<script type="text/javascript" src="gitalk/gitalk.min.js"></script> <script type="text/javascript" src="gitalk/gitalk.min.js"></script>
<script type="text/javascript" src="js/base64.min.js" ></script> <script type="text/javascript" src="js/base64.min.js"></script>
</head> </head>
<body> <body>
<h1>文件预览项目接入和测试界面</h1> <div class="panel-group container" id="accordion">
<div class="panel-group" id="accordion"> <h1>文件预览项目接入和测试界面</h1>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h4 class="panel-title"> <h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" <a data-toggle="collapse" data-parent="#accordion" href="#collapseOne">
href="#collapseOne">
接入说明 接入说明
</a> </a>
</h4> </h4>
</div> </div>
<div id="collapseOne" class="panel-collapse collapse"> <div class="panel-body">
<div class="panel-body"> <div>
<div> 如果你的项目需要接入文件预览项目达到对docx、excel、ppt、jpg等文件的预览效果那么通过在你的项目中加入下面的代码就可以
如果你的项目需要接入文件预览项目达到对docx、excel、ppt、jpg等文件的预览效果那么通过在你的项目中加入下面的代码就可以 成功实现:
成功实现: <pre style="background-color: #2f332a;color: #cccccc">
<pre style="background-color: #2f332a;color: #cccccc"> var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址
var url = 'http://127.0.0.1:8080/file/test.txt'; //要预览文件的访问地址 window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(base64Encode(url)));
window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(base64Encode(url))); </pre>
</pre> </div>
</div> <div>
<div> 新增多图片同时预览功能,接口如下:
新增多图片同时预览功能,接口如下: <pre style="background-color: #2f332a;color: #cccccc">
<pre style="background-color: #2f332a;color: #cccccc"> var fileUrl =url1+"|"+"url2";//多文件使用“|”字符隔开
var fileUrl =url1+"|"+"url2";//多文件使用“|”字符隔开 window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(base64Encode(fileUrl)));
window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(base64Encode(fileUrl))); </pre>
</pre>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -59,104 +57,100 @@ window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(bas
</a> </a>
</h4> </h4>
</div> </div>
<div id="collapseTwo" class="panel-collapse collapse"> <div class="panel-body">
<div class="panel-body"> <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="btnSubmit" value=" "/>
<input type="button" id="btnsubmit" value=" " /> </form>
</form> </div>
</div> <div>
<div> <table id="table" data-pagination="true"></table>
<table id="table" data-pagination="true"></table>
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<h4 class="panel-title"> <h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" <a data-toggle="collapse" data-parent="#accordion" href="#collapseThree">
href="#collapseThree"> 发版记录
更新记录
</a> </a>
</h4> </h4>
</div> </div>
<div id="collapseThree" class="panel-collapse collapse in"> <div class="panel-body">
<div class="panel-body"> <div>
<div> 2020年12月27日 <br>
2020年12月27日 <br> 2020年年终大版本更新架构全面设计代码全面重构代码质量全面提升二次开发更便捷欢迎拉源码品鉴提issue、pr共同建设<br>
2020年年终大版本更新架构全面设计代码全面重构代码质量全面提升二次开发更便捷欢迎拉源码品鉴提issue、pr共同建设 1. 架构模块调整,大量的代码重构代码质量提升N个等级欢迎品鉴<br>
1. 架构模块调整,大量的代码重构代码质量提升N个等级欢迎品鉴<br> 2. 增强XML文件预览效果新增XML文档数结构预览<br>
2. 增强XML文件预览效果新增XML文档数结构预览<br> 3. 新增markdown文件预览支持预览支持md渲染和源文本切换支持<br>
3. 新增markdown文件预览支持预览支持md渲染和源文本切换支持<br> 4. 切换底层web server为jetty解决这个issue<a href="https://github.com/kekingcn/kkFileView/issues/168">#issues/168</a><br>
4. 切换底层web server为jetty解决这个issue<a href="https://github.com/kekingcn/kkFileView/issues/168">#issues/168</a><br> 5. 引入cpdetector解决文件编码识别问题<br>
5. 引入cpdetector解决文件编码识别问题<br> 6. url采用base64+urlencode双编码彻底解决各种奇葩文件名预览问题<br>
6. url采用base64+urlencode双编码彻底解决各种奇葩文件预览问题<br> 7. 新增配置项office.preview.switch.disabled控制offic文件预览切换开关<br>
7. 新增配置项office.preview.switch.disabled控制offic文件预览切换开关<br> 8. 优化文本类型文件预览逻辑采用Base64传输内容避免预览时再次请求文件内容<br>
8. 优化文本类型文件预览逻辑采用Base64传输内容避免预览时再次请求文件内容<br> 9. office预览图片模式禁用图片放大效果达到图片和pdf预览效果一致的体验<br>
9. office预览图片模式禁用图片放大效果达到图片和pdf预览效果一致的体验<br> 10. 直接代码静态设置pdfbox兼容低版本jdk在IDEA中运行也不会有警告提示<br>
10. 直接代码静态设置pdfbox兼容低版本jdk在IDEA中运行也不会有警告提示<br> 11. 移除guavahutool等非必须的工具包减少代码体积<br>
11. 移除guavahutool等非必须的工具包减少代码体积<br> 12. Office组件加载异步化提速应用启动速度最快到5秒内<br>
12. Office组件加载异步化提速应用启动速度最快到5秒内<br> 13. 合理设置预览消费队列的线程数<br>
13. 合理设置预览消费队列的线程数<br> 14. 修复压缩包里文件再次预览失败的bug<br>
14. 修复压缩包里文件再次预览失败的bug<br> 15. 修复图片预览的bug<br><br>
15. 修复图片预览的bug<br><br>
2020年05月20日 <br> 2020年05月20日 <br>
1. 新增支持全局水印并支持通过参数动态改变水印内容<br> 1. 新增支持全局水印并支持通过参数动态改变水印内容<br>
2. 新增支持CAD文件预览<br> 2. 新增支持CAD文件预览<br>
3. 新增base.url配置支持使用nginx反向代理和使用context-path<br> 3. 新增base.url配置支持使用nginx反向代理和使用context-path<br>
4. 支持所有配置项支持从环境变量里读取方便Docker镜像部署和集群中大规模使用<br> 4. 支持所有配置项支持从环境变量里读取方便Docker镜像部署和集群中大规模使用<br>
5. 支持配置限信任站点只能预览来自信任点的文件源保护预览服务不被滥用<br> 5. 支持配置限信任站点只能预览来自信任点的文件源保护预览服务不被滥用<br>
6. 支持配置自定义缓存清理时间cron表达式<br> 6. 支持配置自定义缓存清理时间cron表达式<br>
7. 全部能识别的纯文本直接预览不用再转跳下载.md .java .py等<br> 7. 全部能识别的纯文本直接预览不用再转跳下载.md .java .py等<br>
8. 支持配置限制转换后的PDF文件下载<br> 8. 支持配置限制转换后的PDF文件下载<br>
9. 优化maven打包配置解决 .sh 脚本可能出现换行符问题<br> 9. 优化maven打包配置解决 .sh 脚本可能出现换行符问题<br>
10. 将前端所有CDN依赖放到本地方便没有外网连接的用户使用<br> 10. 将前端所有CDN依赖放到本地方便没有外网连接的用户使用<br>
11. 首页评论服务由搜狐畅言切换到Gitalk<br> 11. 首页评论服务由搜狐畅言切换到Gitalk<br>
12. 修复url中包含特殊字符可能会引起的预览异常<br> 12. 修复url中包含特殊字符可能会引起的预览异常<br>
13. 修复转换文件队列addTask异常<br> 13. 修复转换文件队列addTask异常<br>
14. 修复其他已经问题<br> 14. 修复其他已经问题<br>
15. 官网建设<a href="https://kkfileview.keking.cn">https://kkfileview.keking.cn</a><br> 15. 官网建设<a href="https://kkfileview.keking.cn">https://kkfileview.keking.cn</a><br>
16. 官方Docker镜像仓库建设<a href="https://hub.docker.com/r/keking/kkfileview">https://hub.docker.com/r/keking/kkfileview</a><br><br> 16. 官方Docker镜像仓库建设<a href="https://hub.docker.com/r/keking/kkfileview">https://hub.docker.com/r/keking/kkfileview</a><br><br>
2019年06月18日 <br> 2019年06月18日 <br>
1. 支持自动清理缓存及预览文件<br> 1. 支持自动清理缓存及预览文件<br>
2. 支持http/https下载流url文件预览<br> 2. 支持http/https下载流url文件预览<br>
3. 支持FTP url文件预览<br> 3. 支持FTP url文件预览<br>
4. 加入Docker构建<br><br> 4. 加入Docker构建<br><br>
2019年04月08日 <br> 2019年04月08日 <br>
1. 缓存及队列实现抽象提供JDK和REDIS两种实现(REDIS成为可选依赖)<br> 1. 缓存及队列实现抽象提供JDK和REDIS两种实现(REDIS成为可选依赖)<br>
2. 打包方式提供zip和tar.gz包并提供一键启动脚本<br><br> 2. 打包方式提供zip和tar.gz包并提供一键启动脚本<br><br>
2018年01月19日 <br> 2018年01月19日 <br>
1. 大文件入队提前处理<br> 1. 大文件入队提前处理<br>
1. 新增addTask文件转换入队接口<br> 1. 新增addTask文件转换入队接口<br>
1. 采用redis队列支持kkFIleView接口和异构系统入队两种方式<br><br> 1. 采用redis队列支持kkFIleView接口和异构系统入队两种方式<br><br>
2018年01月15日 <br> 2018年01月15日 <br>
1.首页新增社会化评论框<br><br> 1.首页新增社会化评论框<br><br>
2018年01月12日 <br> 2018年01月12日 <br>
1.新增多图片同时预览<br> 1.新增多图片同时预览<br>
2.支持压缩包内图片轮番预览<br><br> 2.支持压缩包内图片轮番预览<br><br>
2018年01月02日 <br> 2018年01月02日 <br>
1.修复txt等文本编码问题导致预览乱码<br> 1.修复txt等文本编码问题导致预览乱码<br>
2.修复项目模块依赖引入不到的问题<br> 2.修复项目模块依赖引入不到的问题<br>
3.新增spring boot profile支持多环境配置<br> 3.新增spring boot profile支持多环境配置<br>
4.引入pdf.js预览doc等文件支持doc标题生成pdf预览菜单支持手机端预览<br><br> 4.引入pdf.js预览doc等文件支持doc标题生成pdf预览菜单支持手机端预览<br><br>
2017年12月12日<br> 2017年12月12日<br>
1.项目gitee开源:<a href="https://gitee.com/kekingcn/file-online-preview" target="_blank">https://gitee.com/kekingcn/file-online-preview</a><br> 1.项目gitee开源:<a href="https://gitee.com/kekingcn/file-online-preview" target="_blank">https://gitee.com/kekingcn/file-online-preview</a><br>
2.项目github开源:<a href="https://github.com/kekingcn/kkFileView" target="_blank">https://github.com/kekingcn/kkFileView</a> 2.项目github开源:<a href="https://github.com/kekingcn/kkFileView" target="_blank">https://github.com/kekingcn/kkFileView</a>
</div>
</div> </div>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<div id = "comments"></div> <div id="comments"></div>
</div> </div>
</div> </div>
@@ -190,9 +184,9 @@ window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(bas
url: '${baseUrl}deleteFile?fileName=' + encodeURIComponent(fileName), url: '${baseUrl}deleteFile?fileName=' + encodeURIComponent(fileName),
success: function (data) { success: function (data) {
// 删除完成刷新table // 删除完成刷新table
if (1 == data.code) { if (1 === data.code) {
alert(data.msg); alert(data.msg);
} else{ } else {
$('#table').bootstrapTable('refresh', {}); $('#table').bootstrapTable('refresh', {});
} }
}, },
@@ -201,6 +195,7 @@ window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(bas
} }
}) })
} }
$(function () { $(function () {
$('#table').bootstrapTable({ $('#table').bootstrapTable({
url: 'listFiles', url: 'listFiles',
@@ -211,14 +206,14 @@ window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(bas
field: 'action', field: 'action',
title: '操作' title: '操作'
},] },]
}).on('pre-body.bs.table', function (e,data) { }).on('pre-body.bs.table', function (e, data) {
// 每个data添加一列用来操作 // 每个data添加一列用来操作
$(data).each(function (index, item) { $(data).each(function (index, item) {
item.action = "<a class='btn btn-default' target='_blank' href='${baseUrl}onlinePreview?url="+ encodeURIComponent(Base64.encode('${baseUrl}' + item.fileName)) +"'>预览</a>" + item.action = "<a class='btn btn-default' target='_blank' href='${baseUrl}onlinePreview?url=" + encodeURIComponent(Base64.encode('${baseUrl}' + item.fileName)) + "'>预览</a>" +
"<a class='btn btn-default' href='javascript:void(0);' onclick='deleteFile(\""+item.fileName+"\")'>删除</a>"; "<a class='btn btn-default' href='javascript:void(0);' onclick='deleteFile(\"" + item.fileName + "\")'>删除</a>";
}); });
return data; return data;
}).on('post-body.bs.table', function (e,data) { }).on('post-body.bs.table', function (e, data) {
return data; return data;
}); });
@@ -228,12 +223,12 @@ window.open('http://127.0.0.1:8012/picturesPreview?urls='+encodeURIComponent(bas
$(".loading_container").css("height", height).show(); $(".loading_container").css("height", height).show();
} }
$("#btnsubmit").click(function () { $("#btnSubmit").click(function () {
showLoadingDiv(); showLoadingDiv();
$("#fileUpload").ajaxSubmit({ $("#fileUpload").ajaxSubmit({
success: function (data) { success: function (data) {
// 上传完成刷新table // 上传完成刷新table
if (1 == data.code) { if (1 === data.code) {
alert(data.msg); alert(data.msg);
} else { } else {
$('#table').bootstrapTable('refresh', {}); $('#table').bootstrapTable('refresh', {});

View File

@@ -0,0 +1,73 @@
<!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>markdown文本预览</title>
<script src="js/marked.min.js" type="text/javascript"></script>
<#include "*/commonHeader.ftl">
</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>
<script>
/**
* 初始化
*/
window.onload = function () {
$("#markdown_btn").hide()
initWaterMark();
loadMarkdown();
}
/**
* 加载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>
</body>
</html>

View File

@@ -1,23 +1,16 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="zh-cn"> <html lang="zh-cn">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8"/>
<title>多媒体文件预览</title> <title>多媒体文件预览</title>
<link rel="stylesheet" href="plyr/plyr.css" /> <link rel="stylesheet" href="plyr/plyr.css"/>
<script type="text/javascript" src="plyr/plyr.js"></script> <script type="text/javascript" src="plyr/plyr.js"></script>
<script type="text/javascript" src="js/watermark.js"></script> <#include "*/commonHeader.ftl">
<style> <style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
body { body {
background-color: #404040; background-color: #404040;
} }
.m { .m {
width: 1024px; width: 1024px;
margin: 0 auto; margin: 0 auto;
@@ -27,31 +20,13 @@
<body> <body>
<div class="m"> <div class="m">
<video> <video>
<source src="${mediaUrl}" /> <source src="${mediaUrl}"/>
</video> </video>
</div> </div>
<script> <script>
plyr.setup(); plyr.setup();
window.onload = function() { window.onload = function () {
var watermarkTxt = '${watermarkTxt}'; initWaterMark();
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},
});
}
} }
</script> </script>
</body> </body>

View File

@@ -4,15 +4,8 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>PDF图片预览</title> <title>PDF图片预览</title>
<script src="js/lazyload.js"></script> <script src="js/lazyload.js"></script>
<#include "*/commonHeader.ftl">
<style> <style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
body { body {
background-color: #404040; background-color: #404040;
} }
@@ -37,29 +30,10 @@
<#if "false" == switchDisabled> <#if "false" == switchDisabled>
<img src="images/pdf.svg" width="63" height="63" style="position: fixed; cursor: pointer; top: 40%; right: 48px; z-index: 999;" alt="使用PDF预览" title="使用PDF预览" onclick="changePreviewType('pdf')"/> <img src="images/pdf.svg" width="63" height="63" style="position: fixed; cursor: pointer; top: 40%; right: 48px; z-index: 999;" alt="使用PDF预览" title="使用PDF预览" onclick="changePreviewType('pdf')"/>
</#if> </#if>
<script src="js/watermark.js" type="text/javascript"></script>
<script> <script>
window.onload = function () { window.onload = function () {
/*初始化水印*/ /*初始化水印*/
var watermarkTxt = '${watermarkTxt}'; initWaterMark();
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},
});
}
checkImgs(); checkImgs();
}; };
window.onscroll = throttle(checkImgs); window.onscroll = throttle(checkImgs);

View File

@@ -2,41 +2,33 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<title>PDF预览</title> <title>PDF预览</title>
<style type="text/css"> <#include "*/commonHeader.ftl">
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
</style>
</head> </head>
<body> <body>
<#if pdfUrl?contains("http://") || pdfUrl?contains("https://")> <#if pdfUrl?contains("http://") || pdfUrl?contains("https://")>
<#assign finalUrl="${pdfUrl}"> <#assign finalUrl="${pdfUrl}">
<#else> <#else>
<#assign finalUrl="${baseUrl}${pdfUrl}"> <#assign finalUrl="${baseUrl}${pdfUrl}">
</#if> </#if>
<iframe src="" width="100%" frameborder="0"></iframe> <iframe src="" width="100%" frameborder="0"></iframe>
<#if "false" == switchDisabled> <#if "false" == switchDisabled>
<img src="images/jpg.svg" width="63" height="63" style="position: fixed; cursor: pointer; top: 40%; right: 48px; z-index: 999;" alt="使用图片预览" title="使用图片预览" onclick="goForImage()"/> <img src="images/jpg.svg" width="63" height="63"
</#if> style="position: fixed; cursor: pointer; top: 40%; right: 48px; z-index: 999;" alt="使用图片预览" title="使用图片预览"
onclick="goForImage()"/>
</#if>
</body> </body>
<script src="js/watermark.js" type="text/javascript"></script>
<script type="text/javascript"> <script type="text/javascript">
document.getElementsByTagName('iframe')[0].src = "${baseUrl}pdfjs/web/viewer.html?base=${baseUrl}&file="+encodeURIComponent('${finalUrl}')+"&disabledownload=${pdfDownloadDisable}"; document.getElementsByTagName('iframe')[0].src = "${baseUrl}pdfjs/web/viewer.html?base=${baseUrl}&file=" + encodeURIComponent('${finalUrl}') + "&disabledownload=${pdfDownloadDisable}";
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight-10; document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
/** /**
* 页面变化调整高度 * 页面变化调整高度
*/ */
window.onresize = function(){ window.onresize = function () {
var fm = document.getElementsByTagName("iframe")[0]; var fm = document.getElementsByTagName("iframe")[0];
fm.height = window.document.documentElement.clientHeight-10; fm.height = window.document.documentElement.clientHeight - 10;
} }
function goForImage() { function goForImage() {
@@ -46,29 +38,12 @@
} else { } else {
url = url + "&officePreviewType=image"; url = url + "&officePreviewType=image";
} }
window.location.href=url; window.location.href = url;
} }
/*初始化水印*/ /*初始化水印*/
window.onload = function() { window.onload = function () {
var watermarkTxt = '${watermarkTxt}'; initWaterMark();
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},
});
}
} }
</script> </script>
</html> </html>

View File

@@ -4,25 +4,20 @@
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>图片预览</title> <title>图片预览</title>
<link rel="stylesheet" href="css/viewer.min.css"> <link rel="stylesheet" href="css/viewer.min.css">
<script src="js/viewer.min.js"></script>
<#include "*/commonHeader.ftl">
<style> <style>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
body { body {
background-color: #404040; background-color: #404040;
} }
#dowebok { width: 800px; margin: 0 auto; font-size: 0;} #image { width: 800px; margin: 0 auto; font-size: 0;}
#dowebok li { display: inline-block;width: 50px;height: 50px; margin-left: 1%; padding-top: 1%;} #image li { display: inline-block;width: 50px;height: 50px; margin-left: 1%; padding-top: 1%;}
/*#dowebok li img { width: 200%;}*/ /*#dowebok li img { width: 200%;}*/
</style> </style>
</head> </head>
<body> <body>
<ul id="dowebok">
<ul id="image">
<#list imgUrls as img> <#list imgUrls as img>
<#if img?contains("http://") || img?contains("https://")> <#if img?contains("http://") || img?contains("https://")>
<#assign img="${img}"> <#assign img="${img}">
@@ -32,11 +27,9 @@
<li><img id="${img}" url="${img}" src="${img}" width="1px" height="1px"></li> <li><img id="${img}" url="${img}" src="${img}" width="1px" height="1px"></li>
</#list> </#list>
</ul> </ul>
<script src="js/jquery-3.0.0.min.js"></script>
<script src="js/viewer.min.js"></script>
<script src="js/watermark.js" type="text/javascript"></script>
<script> <script>
var viewer = new Viewer(document.getElementById('dowebok'), { var viewer = new Viewer(document.getElementById('image'), {
url: 'src', url: 'src',
navbar: false, navbar: false,
button: false, button: false,
@@ -44,61 +37,10 @@
loop : true loop : true
}); });
document.getElementById("${currentUrl}").click(); document.getElementById("${currentUrl}").click();
// 修改下一页按钮的样式和位置
$(function () {
var outHandler = function(){
$(this).css('background-color','rgba(0, 0, 0, 0)');
};
var overHandler = function(){
$(this).css('background-color','rgba(0, 0, 0, .5)');
};
var next = $("li[data-action=next]");
var prev = $("li[data-action=prev]");
var viewerToolBar = $(".viewer-footer");
// 覆盖按钮父类原始样式
viewerToolBar.css("overflow", "visible");
// 获取文档高度、宽度
var clientHeight = window.innerHeight;
var clientWidth = window.innerWidth;
// 调整样式
var styleCss = {},nextCss={},prevCss={};
styleCss.position = "absolute";
styleCss.top = -clientHeight;
styleCss.width = clientWidth*0.1;
styleCss.height = clientHeight + 52;
// 覆盖原始样式
styleCss.backgroundColor='rgba(0, 0, 0, 0)';
styleCss.borderRadius='inherit';
nextCss.right = "0";
prevCss.left = "0";
next.css($.extend(nextCss, styleCss));
prev.css($.extend(prevCss, styleCss));
next.on('mouseout',outHandler);
next.on('mouseover',overHandler);
prev.on('mouseout',outHandler);
prev.on('mouseover',overHandler);
});
/*初始化水印*/ /*初始化水印*/
window.onload = function() { window.onload = function() {
var watermarkTxt = '${watermarkTxt}'; initWaterMark();
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},
});
}
} }
</script> </script>
</body> </body>

View File

@@ -4,144 +4,49 @@
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"> <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<title>普通文本预览</title> <title>普通文本预览</title>
<#include "*/commonHeader.ftl">
</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"/>
<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> <script>
/** /**
* 初始化 * 初始化
*/ */
window.onload = function () { window.onload = function () {
$("#markdown_btn").hide()
initWaterMark(); initWaterMark();
fetchData();
loadText(); loadText();
loadXmlData()
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},
});
}
}
/**
* 获取文本数据
*/
function fetchData() {
window.textData = Base64.decode($("#textData").val())
window.textPreData = "<pre>" + window.textData + "</pre>";
} }
/** /**
*加载普通文本 *加载普通文本
*/ */
function loadText() { function loadText() {
$("#text").html(window.textPreData); var base64data = $("#textData").val()
var textData = Base64.decode(base64data);
var textPreData = "<xmp style='background-color: #FFFFFF;overflow-y: scroll;border:none'>" + textData + "</xmp>";
$("#text").append(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>
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
width: 100%;
}
#markdown, #xml {
height: 97%;
max-height: 97%;
border: 1px solid #ece7e7;
overflow-y: scroll;
width: 100%;
}
</style>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,73 @@
<!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>xml文本预览</title>
<#include "*/commonHeader.ftl">
<link rel="stylesheet" href="css/xmlTreeViewer.css"/>
<script src="js/xmlTreeViewer.js" type="text/javascript"></script>
</head>
<body>
<input hidden id="textData" value="${textData}"/>
<div class="container">
<div class="panel panel-default">
<div id="xml_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="xml"></div>
</div>
</div>
</div>
<script>
/**
* 初始化
*/
window.onload = function () {
$("#xml_btn").hide()
initWaterMark();
loadXmlData()
}
/**
* 加载xml数据
*/
function loadXmlData() {
var textData = Base64.decode($("#textData").val())
window.textPreData = "<xmp style='background-color: #FFFFFF;overflow-y: scroll;border:none'>" + textData + "</xmp>";
var xmlNode = xmlTreeViewer.parseXML(textData);
window.retNode = xmlTreeViewer.getXMLViewerNode(xmlNode.xml);
$("#xml").html(window.retNode);
}
$(function () {
$("#xml_btn").click(function () {
$("#xml").html(window.retNode);
$("#text_btn").show()
$("#xml_btn").hide()
});
$("#text_btn").click(function () {
$("#xml_btn").show()
$("#text_btn").hide();
$("#xml").html(window.textPreData);
});
});
</script>
</body>
</html>