Compare commits
13 Commits
v3.5
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
| bbeaea14c3 | |||
| 2bb0dd545d | |||
| ac2115114c | |||
| 831550d847 | |||
| 1fa7b4a911 | |||
| bcdb5ce0e6 | |||
| a3485dd9b7 | |||
| 5a28b89f46 | |||
| 58b1b50c2e | |||
| 8f75df15e2 | |||
| 9883d3b064 | |||
| e477ce7048 | |||
| 0985aed0b0 |
@ -28,5 +28,5 @@ ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
|
||||
ENV PATH $PATH:$JAVA_HOME/bin
|
||||
ENV LANG zh_CN.UTF-8
|
||||
ENV LC_ALL zh_CN.UTF-8
|
||||
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-3.5/bin
|
||||
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider","-Dspring.config.location=/opt/kkFileView-3.5/config/application.properties","-jar","/opt/kkFileView-3.5/bin/kkFileView-3.5.jar"]
|
||||
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-3.5.1/bin
|
||||
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider","-Dspring.config.location=/opt/kkFileView-3.5.1/config/application.properties","-jar","/opt/kkFileView-3.5.1/bin/kkFileView-3.5.1.jar"]
|
||||
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<artifactId>filepreview</artifactId>
|
||||
<groupId>cn.keking</groupId>
|
||||
<version>3.5</version>
|
||||
<version>3.5.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>office-plugin</artifactId>
|
||||
@ -24,7 +24,7 @@
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>1.4</version>
|
||||
<version>2.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openoffice</groupId>
|
||||
|
||||
2
pom.xml
2
pom.xml
@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>cn.keking</groupId>
|
||||
<artifactId>filepreview</artifactId>
|
||||
<version>3.5</version>
|
||||
<version>3.5.1</version>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>filepreview</artifactId>
|
||||
<groupId>cn.keking</groupId>
|
||||
<version>3.5</version>
|
||||
<version>3.5.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>kkFileView</artifactId>
|
||||
@ -149,7 +149,7 @@
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.15</version>
|
||||
<version>1.4.16</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
|
||||
@ -192,6 +192,64 @@
|
||||
<artifactId>galimatias</artifactId>
|
||||
<version>0.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 以下是bytedeco 基于opencv ffmpeg封装的javacv,用于视频处理 -->
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>javacv</artifactId>
|
||||
<version>1.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>javacpp</artifactId>
|
||||
<version>1.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 此版本中主要兼容linux和windows系统,如需兼容其他系统平台,请引入对应依赖即可 -->
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>opencv</artifactId>
|
||||
<version>4.1.2-1.5.2</version>
|
||||
<classifier>linux-x86_64</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>opencv</artifactId>
|
||||
<version>4.1.2-1.5.2</version>
|
||||
<classifier>windows-x86_64</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>openblas</artifactId>
|
||||
<version>0.3.6-1.5.1</version>
|
||||
<classifier>linux-x86_64</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>openblas</artifactId>
|
||||
<version>0.3.6-1.5.1</version>
|
||||
<classifier>windows-x86_64</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>ffmpeg</artifactId>
|
||||
<version>4.2.1-1.5.2</version>
|
||||
<classifier>linux-x86_64</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bytedeco</groupId>
|
||||
<artifactId>ffmpeg</artifactId>
|
||||
<version>4.2.1-1.5.2</version>
|
||||
<classifier>windows-x86_64</classifier>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -229,7 +287,8 @@
|
||||
<configuration>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/assembly.xml</descriptor>
|
||||
<descriptor>src/main/assembly/dist-win32.xml</descriptor>
|
||||
<descriptor>src/main/assembly/dist-linux.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../office-plugin/windows-office</directory>
|
||||
<outputDirectory>${file.separator}office</outputDirectory>
|
||||
<outputDirectory>${file.separator}windows-office</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.build.directory}</directory>
|
||||
|
||||
39
server/src/main/assembly/dist-linux.xml
Normal file
39
server/src/main/assembly/dist-linux.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
|
||||
<id>make-assembly</id>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>true</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>src/main/bin</directory>
|
||||
<outputDirectory>${file.separator}bin</outputDirectory>
|
||||
<includes>
|
||||
<include>*.sh</include>
|
||||
</includes>
|
||||
<fileMode>755</fileMode>
|
||||
<lineEnding>unix</lineEnding>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/config</directory>
|
||||
<outputDirectory>${file.separator}config</outputDirectory>
|
||||
<lineEnding>unix</lineEnding>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/log</directory>
|
||||
<outputDirectory>${file.separator}log</outputDirectory>
|
||||
<lineEnding>unix</lineEnding>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.build.directory}</directory>
|
||||
<outputDirectory>${file.separator}bin</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
39
server/src/main/assembly/dist-win32.xml
Normal file
39
server/src/main/assembly/dist-win32.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd">
|
||||
<id>make-assembly</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>true</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>src/main/bin</directory>
|
||||
<outputDirectory>${file.separator}bin</outputDirectory>
|
||||
<includes>
|
||||
<include>*.bat</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/config</directory>
|
||||
<outputDirectory>${file.separator}config</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>src/main/log</directory>
|
||||
<outputDirectory>${file.separator}log</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../office-plugin/windows-office</directory>
|
||||
<outputDirectory>${file.separator}windows-office</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.build.directory}</directory>
|
||||
<outputDirectory>${file.separator}bin</outputDirectory>
|
||||
<includes>
|
||||
<include>*.jar</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
@ -6,4 +6,4 @@ echo Starting kkFileView...
|
||||
echo Please check log file in ../log/kkFileView.log for more information
|
||||
echo You can get help in our official homesite: https://kkFileView.keking.cn
|
||||
echo If this project is helpful to you, please star it on https://gitee.com/kekingcn/file-online-preview/stargazers
|
||||
java -Dspring.config.location=..\config\application.properties -jar kkFileView-3.5.jar -> ..\log\kkFileView.log
|
||||
java -Dspring.config.location=..\config\application.properties -jar kkFileView-3.5.1.jar -> ..\log\kkFileView.log
|
||||
@ -29,4 +29,4 @@ echo "Starting kkFileView..."
|
||||
echo "Please execute ./showlog.sh to check log for more information"
|
||||
echo "You can get help in our official homesite: https://kkFileView.keking.cn"
|
||||
echo "If this project is helpful to you, please star it on https://gitee.com/kekingcn/file-online-preview/stargazers"
|
||||
nohup java -Dfile.encoding=UTF-8 -Dspring.config.location=../config/application.properties -jar kkFileView-3.5.jar > ../log/kkFileView.log 2>&1 &
|
||||
nohup java -Dfile.encoding=UTF-8 -Dspring.config.location=../config/application.properties -jar kkFileView-3.5.1.jar > ../log/kkFileView.log 2>&1 &
|
||||
|
||||
@ -33,7 +33,7 @@ office.home = ${KK_OFFICE_HOME:default}
|
||||
cache.type = ${KK_CACHE_TYPE:jdk}
|
||||
#redis连接,只有当cache.type = redis时才有用
|
||||
spring.redisson.address = ${KK_SPRING_REDISSON_ADDRESS:127.0.0.1:6379}
|
||||
spring.redisson.password = ${KK_SPRING_REDISSON_PASSWORD:123456}
|
||||
spring.redisson.password = ${KK_SPRING_REDISSON_PASSWORD:}
|
||||
#缓存是否自动清理 true 为开启,注释掉或其他值都为关闭
|
||||
cache.clean.enabled = ${KK_CACHE_CLEAN_ENABLED:true}
|
||||
#缓存自动清理时间,cache.clean.enabled = true时才有用,cron表达式,基于Quartz cron
|
||||
@ -55,6 +55,11 @@ cache.enabled = ${KK_CACHE_ENABLED:true}
|
||||
simText = ${KK_SIMTEXT:txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,log,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd}
|
||||
#多媒体类型,默认如下,可自定义添加
|
||||
media = ${KK_MEDIA:mp3,wav,mp4,flv}
|
||||
#是否开启多媒体类型转视频格式转换,目前可转换视频格式有:avi,mov,wmv,3gp,rm
|
||||
#请谨慎开启此功能,建议异步调用添加到处理队列,并且增加任务队列处理线程,防止视频转换占用完线程资源,转换比较耗费时间,并且控制了只能串行处理转换任务
|
||||
media.convert.disable = ${KK_MEDIA_CONVERT_DISABLE:false}
|
||||
#支持转换的视频类型
|
||||
convertMedias = ${KK_CONVERTMEDIAS:avi,mov,wmv,mkv,3gp,rm}
|
||||
#office类型文档(word ppt)样式,默认为图片(image),可配置为pdf(预览时也有按钮切换)
|
||||
office.preview.type = ${KK_OFFICE_PREVIEW_TYPE:image}
|
||||
#是否关闭office预览切换开关,默认为false,可配置为true关闭
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
[#ftl]
|
||||
[#-- @implicitly included --]
|
||||
[#-- @ftlvariable name="initializeMemorySize" type="java.lang.Number" --]
|
||||
[#-- @ftlvariable name="currentUrl" type="java.lang.String" --]
|
||||
[#-- @ftlvariable name="file" type="cn.keking.model.FileAttribute" --]
|
||||
[#-- @ftlvariable name="fileName" type="java.lang.String" --]
|
||||
|
||||
@ -24,6 +24,8 @@ public class ConfigConstants {
|
||||
private static Boolean cacheEnabled;
|
||||
private static String[] simTexts = {};
|
||||
private static String[] medias = {};
|
||||
private static String[] convertMedias = {};
|
||||
private static String mediaConvertDisable;
|
||||
private static String officePreviewType;
|
||||
private static String officePreviewSwitchDisabled;
|
||||
private static String ftpUsername;
|
||||
@ -89,6 +91,33 @@ public class ConfigConstants {
|
||||
ConfigConstants.medias = Media;
|
||||
}
|
||||
|
||||
public static String[] getConvertMedias() {
|
||||
return convertMedias;
|
||||
}
|
||||
|
||||
@Value("${convertMedias:avi,mov,wmv,mkv,3gp,rm}")
|
||||
public void setConvertMedias(String convertMedia) {
|
||||
String[] mediaArr = convertMedia.split(",");
|
||||
setConvertMediaValue(mediaArr);
|
||||
}
|
||||
|
||||
public static void setConvertMediaValue(String[] ConvertMedia) {
|
||||
ConfigConstants.convertMedias = ConvertMedia;
|
||||
}
|
||||
|
||||
public static String getMediaConvertDisable() {
|
||||
return mediaConvertDisable;
|
||||
}
|
||||
|
||||
|
||||
@Value("${media.convert.disable:true}")
|
||||
public void setMediaConvertDisable(String mediaConvertDisable) {
|
||||
setMediaConvertDisableValue(mediaConvertDisable);
|
||||
}
|
||||
public static void setMediaConvertDisableValue(String mediaConvertDisable) {
|
||||
ConfigConstants.mediaConvertDisable = mediaConvertDisable;
|
||||
}
|
||||
|
||||
public static String getOfficePreviewType() {
|
||||
return officePreviewType;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ public class ConfigRefreshComponent {
|
||||
text = properties.getProperty("simText", ConfigConstants.DEFAULT_TXT_TYPE);
|
||||
media = properties.getProperty("media", ConfigConstants.DEFAULT_MEDIA_TYPE);
|
||||
officePreviewType = properties.getProperty("office.preview.type", ConfigConstants.DEFAULT_OFFICE_PREVIEW_TYPE);
|
||||
officePreviewSwitchDisabled = properties.getProperty("office.preview.switch.disabled", ConfigConstants.DEFAULT_OFFICE_PREVIEW_TYPE);
|
||||
officePreviewSwitchDisabled = properties.getProperty("office.preview.switch.disabled", ConfigConstants.DEFAULT_OFFICE_PREVIEW_SWITCH_DISABLED);
|
||||
ftpUsername = properties.getProperty("ftp.username", ConfigConstants.DEFAULT_FTP_USERNAME);
|
||||
ftpPassword = properties.getProperty("ftp.password", ConfigConstants.DEFAULT_FTP_PASSWORD);
|
||||
ftpControlEncoding = properties.getProperty("ftp.control.encoding", ConfigConstants.DEFAULT_FTP_CONTROL_ENCODING);
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package cn.keking.config;
|
||||
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.redisson.client.codec.Codec;
|
||||
import org.redisson.config.Config;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
@ -63,7 +64,7 @@ public class RedissonConfig {
|
||||
.setConnectTimeout(connectTimeout)
|
||||
.setIdleConnectionTimeout(idleConnectionTimeout)
|
||||
.setPingTimeout(pingTimeout)
|
||||
.setPassword(password);
|
||||
.setPassword(StringUtils.trimToNull(password));
|
||||
Codec codec=(Codec) ClassUtils.forName(getCodec(), ClassUtils.getDefaultClassLoader()).newInstance();
|
||||
config.setCodec(codec);
|
||||
config.setThreads(thread);
|
||||
|
||||
@ -33,6 +33,7 @@ public enum FileType {
|
||||
private static final String[] SSIM_TEXT_TYPES = ConfigConstants.getSimText();
|
||||
private static final String[] CODES = {"java", "c", "php", "go", "python", "py", "js", "html", "ftl", "css", "lua", "sh", "rb", "yml", "json", "h", "cpp", "cs", "aspx", "jsp"};
|
||||
private static final String[] MEDIA_TYPES = ConfigConstants.getMedia();
|
||||
public static final String[] MEDIA_TYPES_CONVERT = ConfigConstants.getConvertMedias();
|
||||
private static final Map<String, FileType> FILE_TYPE_MAPPER = new HashMap<>();
|
||||
|
||||
static {
|
||||
@ -51,6 +52,9 @@ public enum FileType {
|
||||
for (String media : MEDIA_TYPES) {
|
||||
FILE_TYPE_MAPPER.put(media, FileType.MEDIA);
|
||||
}
|
||||
for (String media : MEDIA_TYPES_CONVERT) {
|
||||
FILE_TYPE_MAPPER.put(media, FileType.MEDIA);
|
||||
}
|
||||
for (String tif : TIFF_TYPES) {
|
||||
FILE_TYPE_MAPPER.put(tif, FileType.TIFF);
|
||||
}
|
||||
|
||||
@ -286,4 +286,27 @@ public class FileHandlerService {
|
||||
}
|
||||
return attribute;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 已转换过的视频文件集合(缓存)
|
||||
*/
|
||||
public Map<String, String> listConvertedMedias() {
|
||||
return cacheService.getMediaConvertCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加转换后的视频文件缓存
|
||||
* @param fileName
|
||||
* @param value
|
||||
*/
|
||||
public void addConvertedMedias(String fileName, String value) {
|
||||
cacheService.putMediaConvertCache(fileName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 已转换视频文件缓存,根据文件名获取
|
||||
*/
|
||||
public String getConvertedMedias(String key) {
|
||||
return cacheService.getMediaConvertCache(key);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,15 +12,18 @@ public interface CacheService {
|
||||
String FILE_PREVIEW_PDF_KEY = "converted-preview-pdf-file";
|
||||
String FILE_PREVIEW_IMGS_KEY = "converted-preview-imgs-file";//压缩包内图片文件集合
|
||||
String FILE_PREVIEW_PDF_IMGS_KEY = "converted-preview-pdfimgs-file";
|
||||
String FILE_PREVIEW_MEDIA_CONVERT_KEY = "converted-preview-media-file";
|
||||
String TASK_QUEUE_NAME = "convert-task";
|
||||
|
||||
Integer DEFAULT_PDF_CAPACITY = 500000;
|
||||
Integer DEFAULT_IMG_CAPACITY = 500000;
|
||||
Integer DEFAULT_PDFIMG_CAPACITY = 500000;
|
||||
Integer DEFAULT_MEDIACONVERT_CAPACITY = 500000;
|
||||
|
||||
void initPDFCachePool(Integer capacity);
|
||||
void initIMGCachePool(Integer capacity);
|
||||
void initPdfImagesCachePool(Integer capacity);
|
||||
void initMediaConvertCachePool(Integer capacity);
|
||||
void putPDFCache(String key, String value);
|
||||
void putImgCache(String key, List<String> value);
|
||||
Map<String, String> getPDFCache();
|
||||
@ -29,6 +32,9 @@ public interface CacheService {
|
||||
List<String> getImgCache(String key);
|
||||
Integer getPdfImageCache(String key);
|
||||
void putPdfImageCache(String pdfFilePath, int num);
|
||||
Map<String, String> getMediaConvertCache();
|
||||
void putMediaConvertCache(String key, String value);
|
||||
String getMediaConvertCache(String key);
|
||||
void cleanCache();
|
||||
void addQueueTask(String url);
|
||||
String takeQueueTask() throws InterruptedException;
|
||||
|
||||
@ -26,6 +26,7 @@ public class CacheServiceJDKImpl implements CacheService {
|
||||
private Map<String, String> pdfCache;
|
||||
private Map<String, List<String>> imgCache;
|
||||
private Map<String, Integer> pdfImagesCache;
|
||||
private Map<String, String> mediaConvertCache;
|
||||
private static final int QUEUE_SIZE = 500000;
|
||||
private final BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(QUEUE_SIZE);
|
||||
|
||||
@ -34,6 +35,7 @@ public class CacheServiceJDKImpl implements CacheService {
|
||||
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
|
||||
initIMGCachePool(CacheService.DEFAULT_IMG_CAPACITY);
|
||||
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
|
||||
initMediaConvertCachePool(CacheService.DEFAULT_MEDIACONVERT_CAPACITY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -79,6 +81,21 @@ public class CacheServiceJDKImpl implements CacheService {
|
||||
pdfImagesCache.put(pdfFilePath, num);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMediaConvertCache() {
|
||||
return mediaConvertCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putMediaConvertCache(String key, String value) {
|
||||
mediaConvertCache.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMediaConvertCache(String key) {
|
||||
return mediaConvertCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanCache() {
|
||||
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
|
||||
@ -116,4 +133,12 @@ public class CacheServiceJDKImpl implements CacheService {
|
||||
.maximumWeightedCapacity(capacity).weigher(Weighers.singleton())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initMediaConvertCachePool(Integer capacity) {
|
||||
mediaConvertCache = new ConcurrentLinkedHashMap.Builder<String, String>()
|
||||
.maximumWeightedCapacity(capacity).weigher(Weighers.singleton())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -34,6 +34,11 @@ public class CacheServiceRedisImpl implements CacheService {
|
||||
@Override
|
||||
public void initPdfImagesCachePool(Integer capacity) { }
|
||||
|
||||
@Override
|
||||
public void initMediaConvertCachePool(Integer capacity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPDFCache(String key, String value) {
|
||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(FILE_PREVIEW_PDF_KEY);
|
||||
@ -80,6 +85,23 @@ public class CacheServiceRedisImpl implements CacheService {
|
||||
convertedList.fastPut(pdfFilePath, num);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMediaConvertCache() {
|
||||
return redissonClient.getMapCache(FILE_PREVIEW_MEDIA_CONVERT_KEY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putMediaConvertCache(String key, String value) {
|
||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(FILE_PREVIEW_MEDIA_CONVERT_KEY);
|
||||
convertedList.fastPut(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMediaConvertCache(String key) {
|
||||
RMapCache<String, String> convertedList = redissonClient.getMapCache(FILE_PREVIEW_MEDIA_CONVERT_KEY);
|
||||
return convertedList.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanCache() {
|
||||
cleanPdfCache();
|
||||
|
||||
@ -73,6 +73,11 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initMediaConvertCachePool(Integer capacity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putPDFCache(String key, String value) {
|
||||
try {
|
||||
@ -171,6 +176,40 @@ public class CacheServiceRocksDBImpl implements CacheService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMediaConvertCache() {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
try{
|
||||
result = (Map<String, String>) toObject(db.get(FILE_PREVIEW_MEDIA_CONVERT_KEY.getBytes()));
|
||||
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||
LOGGER.error("Get from RocksDB Exception" + e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putMediaConvertCache(String key, String value) {
|
||||
try {
|
||||
Map<String, String> mediaConvertCacheItem = getMediaConvertCache();
|
||||
mediaConvertCacheItem.put(key, value);
|
||||
db.put(FILE_PREVIEW_MEDIA_CONVERT_KEY.getBytes(), toByteArray(mediaConvertCacheItem));
|
||||
} catch (RocksDBException | IOException e) {
|
||||
LOGGER.error("Put into RocksDB Exception" + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMediaConvertCache(String key) {
|
||||
String result = "";
|
||||
try{
|
||||
Map<String, String> map = (Map<String, String>) toObject(db.get(FILE_PREVIEW_MEDIA_CONVERT_KEY.getBytes()));
|
||||
result = map.get(key);
|
||||
} catch (RocksDBException | IOException | ClassNotFoundException e) {
|
||||
LOGGER.error("Get from RocksDB Exception" + e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanCache() {
|
||||
try {
|
||||
|
||||
@ -1,13 +1,21 @@
|
||||
package cn.keking.service.impl;
|
||||
|
||||
import cn.keking.config.ConfigConstants;
|
||||
import cn.keking.model.FileAttribute;
|
||||
import cn.keking.model.FileType;
|
||||
import cn.keking.model.ReturnResponse;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.DownloadUtils;
|
||||
import cn.keking.service.FileHandlerService;
|
||||
import cn.keking.web.filter.BaseUrlFilter;
|
||||
import org.artofsolving.jodconverter.util.ConfigUtils;
|
||||
import org.bytedeco.ffmpeg.global.avcodec;
|
||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||
import org.bytedeco.javacv.FFmpegFrameRecorder;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author : kl
|
||||
@ -21,6 +29,8 @@ public class MediaFilePreviewImpl implements FilePreview {
|
||||
private final FileHandlerService fileHandlerService;
|
||||
private final OtherFilePreviewImpl otherFilePreview;
|
||||
|
||||
private static Object LOCK=new Object();
|
||||
|
||||
public MediaFilePreviewImpl(FileHandlerService fileHandlerService, OtherFilePreviewImpl otherFilePreview) {
|
||||
this.fileHandlerService = fileHandlerService;
|
||||
this.otherFilePreview = otherFilePreview;
|
||||
@ -34,14 +44,123 @@ public class MediaFilePreviewImpl implements FilePreview {
|
||||
if (response.isFailure()) {
|
||||
return otherFilePreview.notSupportedFile(model, fileAttribute, response.getMsg());
|
||||
} else {
|
||||
model.addAttribute("mediaUrl", BaseUrlFilter.getBaseUrl() + fileHandlerService.getRelativePath(response.getContent()));
|
||||
url=BaseUrlFilter.getBaseUrl() + fileHandlerService.getRelativePath(response.getContent());
|
||||
fileAttribute.setUrl(url);
|
||||
}
|
||||
} else {
|
||||
model.addAttribute("mediaUrl", url);
|
||||
}
|
||||
|
||||
if(checkNeedConvert(fileAttribute.getSuffix())){
|
||||
url=convertUrl(fileAttribute);
|
||||
}else{
|
||||
//正常media类型
|
||||
String[] medias = ConfigConstants.getMedia();
|
||||
for(String media:medias){
|
||||
if(media.equals(fileAttribute.getSuffix())){
|
||||
model.addAttribute("mediaUrl", url);
|
||||
return MEDIA_FILE_PREVIEW_PAGE;
|
||||
}
|
||||
}
|
||||
return otherFilePreview.notSupportedFile(model, fileAttribute, "暂不支持");
|
||||
}
|
||||
model.addAttribute("mediaUrl", url);
|
||||
return MEDIA_FILE_PREVIEW_PAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查视频文件处理逻辑
|
||||
* 返回处理过后的url
|
||||
* @return url
|
||||
*/
|
||||
private String convertUrl(FileAttribute fileAttribute) {
|
||||
String url = fileAttribute.getUrl();
|
||||
if(fileHandlerService.listConvertedMedias().containsKey(url)){
|
||||
url= fileHandlerService.getConvertedMedias(url);
|
||||
}else{
|
||||
if(!fileHandlerService.listConvertedMedias().containsKey(url)){
|
||||
synchronized(LOCK){
|
||||
if(!fileHandlerService.listConvertedMedias().containsKey(url)){
|
||||
String convertedUrl=convertToMp4(fileAttribute);
|
||||
//加入缓存
|
||||
fileHandlerService.addConvertedMedias(url,convertedUrl);
|
||||
url=convertedUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查视频文件转换是否已开启,以及当前文件是否需要转换
|
||||
* @return
|
||||
*/
|
||||
private boolean checkNeedConvert(String suffix) {
|
||||
//1.检查开关是否开启
|
||||
if("false".equals(ConfigConstants.getMediaConvertDisable())){
|
||||
return false;
|
||||
}
|
||||
//2.检查当前文件是否需要转换
|
||||
String[] mediaTypesConvert = FileType.MEDIA_TYPES_CONVERT;
|
||||
String type = suffix;
|
||||
for(String temp : mediaTypesConvert){
|
||||
if(type.equals(temp)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将浏览器不兼容视频格式转换成MP4
|
||||
* @param fileAttribute
|
||||
* @return
|
||||
*/
|
||||
private static String convertToMp4(FileAttribute fileAttribute) {
|
||||
|
||||
//说明:这里做临时处理,取上传文件的目录
|
||||
String homePath = ConfigUtils.getHomePath();
|
||||
String filePath = homePath+File.separator+"file"+File.separator+"demo"+File.separator+fileAttribute.getName();
|
||||
String convertFileName=fileAttribute.getUrl().replace(fileAttribute.getSuffix(),"mp4");
|
||||
|
||||
File file=new File(filePath);
|
||||
FFmpegFrameGrabber frameGrabber = new FFmpegFrameGrabber(file);
|
||||
String fileName = null;
|
||||
Frame captured_frame = null;
|
||||
FFmpegFrameRecorder recorder = null;
|
||||
try {
|
||||
fileName = file.getAbsolutePath().replace(fileAttribute.getSuffix(),"mp4");
|
||||
File desFile=new File(fileName);
|
||||
//判断一下防止穿透缓存
|
||||
if(desFile.exists()){
|
||||
return fileName;
|
||||
}
|
||||
|
||||
frameGrabber.start();
|
||||
recorder = new FFmpegFrameRecorder(fileName, frameGrabber.getImageWidth(), frameGrabber.getImageHeight(), frameGrabber.getAudioChannels());
|
||||
recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264); //avcodec.AV_CODEC_ID_H264 //AV_CODEC_ID_MPEG4
|
||||
recorder.setFormat("mp4");
|
||||
recorder.setFrameRate(frameGrabber.getFrameRate());
|
||||
//recorder.setSampleFormat(frameGrabber.getSampleFormat()); //
|
||||
recorder.setSampleRate(frameGrabber.getSampleRate());
|
||||
|
||||
recorder.setAudioChannels(frameGrabber.getAudioChannels());
|
||||
recorder.setFrameRate(frameGrabber.getFrameRate());
|
||||
recorder.start();
|
||||
while ((captured_frame = frameGrabber.grabFrame()) != null) {
|
||||
try {
|
||||
recorder.setTimestamp(frameGrabber.getTimestamp());
|
||||
recorder.record(captured_frame);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
recorder.stop();
|
||||
recorder.release();
|
||||
frameGrabber.stop();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//是否删除源文件
|
||||
//file.delete();
|
||||
return convertFileName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,10 @@ package cn.keking.service.impl;
|
||||
|
||||
import cn.keking.model.FileAttribute;
|
||||
import cn.keking.service.FilePreview;
|
||||
import cn.keking.utils.WebUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* tiff 图片文件处理
|
||||
@ -14,6 +16,9 @@ import org.springframework.ui.Model;
|
||||
public class TiffFilePreviewImpl implements FilePreview {
|
||||
|
||||
private final PictureFilePreviewImpl pictureFilePreview;
|
||||
private static final String INITIALIZE_MEMORY_SIZE = "initializeMemorySize";
|
||||
//默认初始化 50MB 内存
|
||||
private static final long INITIALIZE_MEMORY_SIZE_VALUE_DEFAULT = 1024L * 1024 * 50;
|
||||
|
||||
public TiffFilePreviewImpl(PictureFilePreviewImpl pictureFilePreview) {
|
||||
this.pictureFilePreview = pictureFilePreview;
|
||||
@ -22,6 +27,12 @@ public class TiffFilePreviewImpl implements FilePreview {
|
||||
@Override
|
||||
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
|
||||
pictureFilePreview.filePreviewHandle(url,model,fileAttribute);
|
||||
String fileSize = WebUtils.getUrlParameterReg(url,INITIALIZE_MEMORY_SIZE);
|
||||
if(StringUtils.hasText(fileSize)){
|
||||
model.addAttribute(INITIALIZE_MEMORY_SIZE,fileSize);
|
||||
}else {
|
||||
model.addAttribute(INITIALIZE_MEMORY_SIZE,Long.toString(INITIALIZE_MEMORY_SIZE_VALUE_DEFAULT));
|
||||
}
|
||||
return TIFF_FILE_PREVIEW_PAGE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,7 @@ public class KkFileUtils {
|
||||
* @return 文件后缀
|
||||
*/
|
||||
public static String suffixFromFileName(String fileName) {
|
||||
return fileName.substring(fileName.lastIndexOf(".") + 1);
|
||||
return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -30,8 +30,6 @@ public class FilterConfiguration {
|
||||
Set<String> filterUri = new HashSet<>();
|
||||
filterUri.add("/onlinePreview");
|
||||
filterUri.add("/picturesPreview");
|
||||
filterUri.add("/getCorsFile");
|
||||
filterUri.add("/addTask");
|
||||
TrustHostFilter filter = new TrustHostFilter();
|
||||
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
|
||||
registrationBean.setFilter(filter);
|
||||
|
||||
@ -2019,7 +2019,7 @@ var validateFileURL;
|
||||
{
|
||||
var HOSTED_VIEWER_ORIGINS = ["null", "http://mozilla.github.io", "https://mozilla.github.io"];
|
||||
|
||||
validateFileURL = function validateFileURL(file, base) {
|
||||
validateFileURL = function validateFileURL(file) {
|
||||
if (file === undefined) {
|
||||
return;
|
||||
}
|
||||
@ -2036,7 +2036,7 @@ var validateFileURL;
|
||||
protocol = _ref11.protocol;
|
||||
|
||||
if (origin !== viewerOrigin && protocol !== "blob:") {
|
||||
return (base.endsWith('/') ? base : base + '/') + 'getCorsFile?urlPath=' + encodeURIComponent(file);
|
||||
throw new Error("file origin does not match viewer's");
|
||||
}
|
||||
} catch (ex) {
|
||||
var message = ex && ex.message;
|
||||
@ -2089,14 +2089,12 @@ function loadAndEnablePDFBug(enabledTabs) {
|
||||
function webViewerInitialized() {
|
||||
var appConfig = PDFViewerApplication.appConfig;
|
||||
var file;
|
||||
var base;
|
||||
var disableDownload;
|
||||
var queryString = document.location.search.substring(1);
|
||||
var params = (0, _ui_utils.parseQueryString)(queryString);
|
||||
file = "file" in params ? params.file : _app_options.AppOptions.get("defaultUrl");
|
||||
base = 'base' in params ? params.base : appConfig.defaultUrl;
|
||||
disableDownload = 'disabledownload' in params ? params.disabledownload : 'false';
|
||||
validateFileURL(file, base);
|
||||
validateFileURL(file);
|
||||
var fileInput = document.createElement("input");
|
||||
fileInput.id = appConfig.openFileInputName;
|
||||
fileInput.className = "fileInput";
|
||||
|
||||
@ -21,7 +21,12 @@
|
||||
</#if>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}pdfjs/web/viewer.html?base=${baseUrl}&file=" + encodeURIComponent('${finalUrl}') + "&disabledownload=${pdfDownloadDisable}";
|
||||
var url = '${finalUrl}';
|
||||
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';
|
||||
if (!url.startsWith(baseUrl)) {
|
||||
url = baseUrl + 'getCorsFile?urlPath=' + encodeURIComponent(url);
|
||||
}
|
||||
document.getElementsByTagName('iframe')[0].src = "${baseUrl}pdfjs/web/viewer.html?file=" + encodeURIComponent(url) + "&disabledownload=${pdfDownloadDisable}";
|
||||
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
|
||||
/**
|
||||
* 页面变化调整高度
|
||||
|
||||
@ -30,6 +30,9 @@
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.open('GET', $("#currentUrl").val());
|
||||
var config = {};
|
||||
config.TOTAL_MEMORY = ${initializeMemorySize};
|
||||
Tiff.initialize(config)
|
||||
xhr.onload = function (e) {
|
||||
var tiff = new Tiff({buffer: xhr.response});
|
||||
var canvas = tiff.toCanvas();
|
||||
|
||||
Reference in New Issue
Block a user