Compare commits

..

91 Commits

Author SHA1 Message Date
陈精华
b1fdbd26a3 新功能点:全部能识别的纯文本直接预览,不用再转跳下载(.md、.java、.py等浏览器不认识的后缀名) 2019-10-25 15:16:25 +08:00
陈精华
fa7241bd4e 新功能点:所有配置项支持从环境变量里读取,方便Docker镜像部署 2019-10-25 15:16:25 +08:00
陈精华
8fdf462c6c 新功能点:缓存清理时间cron表达式支持自定义 link #I1147X 2019-10-25 15:16:25 +08:00
陈精华
f7c7411bcf fixup! 优化:目录调整,符合maven规范;maven编译指定.sh脚本换行符为unix换行 2019-10-25 15:16:25 +08:00
陈精华
845cb2e657 修复:参数包含特殊字符时url解码失败 2019-10-25 15:16:25 +08:00
陈精华
a4bfde68bd 优化:目录调整,符合maven规范;maven编译指定.sh脚本换行符为unix换行 2019-10-25 15:16:25 +08:00
陈精华
19d1ba6cf9 优化:(内部)移除为pdf文档提供base64缩略图 2019-10-25 15:16:25 +08:00
陈精华
1060bdd00f 新功能点:支持base url配置(主要用于nginx反向代理等) 2019-10-17 11:36:43 +08:00
陈精华
8c2fb2bdee 优化:默认启用缓存 2019-10-17 11:36:43 +08:00
陈精华
0fe75387eb 优化:启动脚本加入官网链接,点star推广等文案 close #I1148F 2019-09-16 11:49:49 +08:00
陈精华
fbea49e54f 优化:加入查看日志脚本 2019-09-16 11:49:49 +08:00
陈精华
41a72798d9 优化:去除可能导致文件不更新的缓存 2019-09-16 11:49:49 +08:00
陈精华
03cc185085 修复:压缩包中文件名有空格异常 2019-09-16 11:49:49 +08:00
陈精华
bfbd8ee25e 新功能点:(内部)为pdf文档提供base64缩略图 2019-09-10 18:24:06 +08:00
陈精华
f3f36169ff 优化:压缩文件名支持有特殊字符 2019-09-10 18:24:06 +08:00
陈精华
2df88544d3 修复:macOS下office组件默认路径错误 2019-09-10 18:24:06 +08:00
陈精华
6b744d77c7 修复:RocksDB缓存实现压缩包图片url缓存失效 2019-09-10 18:24:06 +08:00
doras
ba57dedebb "加入是否启用缓存配置项"后,excel转成的html文件不再转换编码,修复因此出现的乱码问题 2019-08-26 11:17:37 +08:00
陈精华
affd5b3057 图片和pdf预览模式切换按钮大小调整 2019-08-23 18:18:37 +08:00
陈精华
30c3128995 修复压缩文件中文fileKey未编码 link #I111PD 2019-08-23 18:18:37 +08:00
陈精华
b003a05775 加入是否启用缓存配置项 2019-08-23 18:18:37 +08:00
陈精华
98ec3d7dab 首页预览打开新页面 2019-08-23 18:18:37 +08:00
陈精华
69e23dbb99 shutdown脚本更新 2019-08-23 18:18:37 +08:00
陈精华
47bda1023a 修复Chrome76+删除弹出新窗口 2019-08-23 18:18:37 +08:00
陈精华
fd538a74af 中文语言环境 2019-08-23 18:18:37 +08:00
陈精华
300d213a7a cdn资源不指定http/https 2019-08-23 18:18:37 +08:00
陈精华
4c0a70f300 2.2.0迭代 2019-08-23 18:18:37 +08:00
陈精华
8798d344b6 2.1.2版 2019-07-30 16:31:53 +08:00
陈精华
63e62ab57b pdf.js使用里面一个bug 2019-07-30 16:31:53 +08:00
陈精华
9a027674ac 演示首页兼容IE 2019-07-30 16:31:53 +08:00
1045485954@qq.com
e4407467dd IE兼容性问题,目前已兼容到IE9 2019-07-17 09:03:32 +08:00
陈精华
551eeb0390 2.1.1版 2019-07-09 10:46:21 +08:00
陈精华
11d6ad1ed3 修复文件下载流URL参数中包含中文URL编码不正确导致HTTP-400异常 2019-07-09 10:46:21 +08:00
陈精华
e57db6925c 修复config.js 404问题 2019-07-09 10:46:21 +08:00
陈精华
87096364d8 首页示例修改、首页更新记录 2019-07-09 10:46:21 +08:00
陈精华
ad8027a7d0 2.1.1迭代 2019-07-09 10:46:21 +08:00
陈精华
9786fa8275 2.1.0版 2019-06-19 15:24:24 +08:00
陈精华
37762cf034 支持FTP文件地址作为预览源url 2019-06-19 15:24:24 +08:00
陈精华
a78f1e5f8e Docker构建 2019-06-19 15:24:24 +08:00
陈精华
440b8030e0 新增Docker构建 2019-06-19 15:24:24 +08:00
陈精华
fb7cdfbef7 支持http/https文件流作为预览源url 2019-06-19 15:24:24 +08:00
陈精华
cf1ee9c631 支持自动清理预览文件及缓存 2019-06-19 15:24:24 +08:00
陈精华
13123f8f9d addTask转码优化 2019-06-19 15:24:24 +08:00
陈精华
189bc3965d 2.1.0迭代 2019-06-19 15:24:24 +08:00
kl
0aa7444dba Update pom.xml 2019-05-30 09:08:08 +08:00
陈精华
628efec6bd 2.0.2版 2019-05-23 09:53:37 +08:00
陈精华
6d0846a551 修复rocksdb缓存只缓存一条数据问题 2019-05-23 09:53:37 +08:00
陈精华
41d9015023 支持flv视频预览 2019-05-23 09:53:37 +08:00
陈精华
3f40b60c64 支持7z文件预览 2019-05-23 09:53:37 +08:00
陈精华
f244054462 优化读取动态配置 2019-05-23 09:53:37 +08:00
陈精华
37fbc98827 2.0.2迭代 2019-05-23 09:53:37 +08:00
陈精华
795cf3393e 2.0.1版 2019-05-09 15:20:15 +08:00
陈精华
70323b8ee3 pdf预览支持url中有中文或特殊字符 2019-05-09 15:20:15 +08:00
陈精华
67686e99f0 修复excel预览网页乱码问题 2019-05-09 15:20:15 +08:00
陈精华
90554462dc pdf默认预览模式也从配置文件中取,和word ppt统一 2019-05-09 15:20:15 +08:00
kl
ba3084d698 Update README.md 2019-05-09 09:18:54 +08:00
陈精华
3813f75f65 2.0版本 2019-05-07 10:16:26 +08:00
陈精华
a663e99bcd 背景色统一 2019-04-28 13:55:40 +08:00
陈精华
d517ab4e6f 替换pdf和图片预览相互转跳按钮图标 2019-04-28 13:55:40 +08:00
陈精华
29726c11a3 PDF预览也支持图片模式和查看大图 2019-04-28 13:55:40 +08:00
陈精华
336a18ade7 office预览只有PDF转图片 2019-04-26 15:35:43 +08:00
陈精华
53814fe6ab office图片&PDF预览背景色统一 2019-04-26 14:54:09 +08:00
陈精华
50fb586e6f office图片预览打开大图新开窗口 2019-04-26 14:25:35 +08:00
陈精华
a49ee9d726 图片预览可在viewjs中大图预览&翻页 2019-04-26 14:15:08 +08:00
陈精华
ae40d0233b 加入shutdown脚本 2019-04-26 14:15:08 +08:00
陈精华
8f7c13850e 修复调试时只打开jodconverter-web目录里读不到配置文件异常 2019-04-26 14:15:08 +08:00
陈精华
b4d3419797 word、ppt文档新增图片预览模式 2019-04-26 09:04:34 +08:00
陈精华
68aa5db66b RocksDB缓存实现,并更换默认实现为RocksDB 2019-04-23 11:40:44 +08:00
陈精华
7e8de7c754 解压相关 2019-04-18 16:14:58 +08:00
陈精华
f989fbf9c9 优先使用自定义office.home 2019-04-18 11:53:59 +08:00
陈精华
af8ddc10da 文件转换编码默认根据操作系统获取,变为可选配置
文本和多媒体类型添加默认值,变为可选配置
2019-04-17 13:32:14 +08:00
陈精华
3713e6e550 MacOS下office安装路径更新 2019-04-17 13:32:14 +08:00
陈精华
4a7ba07df1 file.Dir变为选配置添加其默认值 2019-04-16 22:10:48 +08:00
陈精华
b625381de3 脚本修改 2019-04-16 16:11:22 +08:00
陈精华
0968ac774a 脚本修改 2019-04-16 16:11:22 +08:00
陈精华
0db6b23bf7 Linux下集成OpenOffice 2019-04-16 16:11:22 +08:00
陈精华
6dc10e8df4 解决tar包office目录层级过长问题 2019-04-16 16:11:22 +08:00
陈精华
9976f0ae99 dev和release区分开 2019-04-16 16:11:22 +08:00
陈精华
55537d3a25 Windows下集成OpenOffice 2019-04-16 16:11:22 +08:00
陈精华
02e116fd8a 完善启动脚本 2019-04-16 16:11:22 +08:00
陈精华
5af3a97720 支持部分配置在运行时动态改变 2019-04-16 16:11:22 +08:00
陈精华
bf08c2c26f 更新记录 2019-04-16 16:11:22 +08:00
陈精华
236ed405f2 启动脚本&配置文件 2019-04-16 16:11:22 +08:00
陈精华
0fb02e3ccb 打包为zip和tar.gz包 2019-04-16 16:11:22 +08:00
陈精华
3dd6609fd6 缓存及队列实现抽象,提供JDK和REDIS两种实现 2019-04-16 16:11:22 +08:00
kl
dd876792c7 Update pom.xml 2018-10-22 11:34:30 +08:00
kl
3b79ef31e8 Update pom.xml
更新jar版本依赖,老版本有安全风险
2018-10-17 09:09:02 +08:00
kl
deb3abcac1 Merge remote-tracking branch 'origin/master' 2018-03-26 17:06:42 +08:00
kl
1c1a945959 使用畅言替换友言社评服务 2018-03-26 17:03:20 +08:00
duanmuxiangxiao
d1c5211d03 viewerjs版本升级release 1.0.0-rc.1 2018-03-26 16:48:02 +08:00
duanmuxiangxiao
d73bc3a031 图片轮播,修改图片切换按钮样式 2018-03-26 13:39:54 +08:00
3674 changed files with 674563 additions and 367 deletions

5
.gitignore vendored
View File

@@ -28,7 +28,6 @@ nbdist/
.classpath
.project
**/.settings
**/bin/
**/build/
**/.externalToolBuilders/
*.iml
@@ -38,4 +37,6 @@ nbdist/
/producer/tmp
/.temfile
.temfile
convertedFile/
convertedFile/
jodconverter-web/src/main/cache/
jodconverter-web/src/main/file/

34
Dockerfile Normal file
View File

@@ -0,0 +1,34 @@
FROM centos:centos7.6.1810
MAINTAINER chenjh "842761733@qq.com"
ADD jodconverter-web/target/kkFileView-*.tar.gz /opt/
COPY fonts/* /usr/share/fonts/chienes/
RUN yum install -y kde-l10n-Chinese &&\
yum install -y glibc-common &&\
yum install -y fontconfig &&\
yum install -y mkfontscale &&\
localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 &&\
echo "LANG=zh_CN.UTF-8" > /etc/locale.conf &&\
source /etc/locale.conf &&\
export LANG=zh_CN.UTF-8 &&\
LANG="zh_CN.UTF-8" &&\
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&\
yum install -y java-1.8.0-openjdk.x86_64 &&\
yum install -y wget &&\
yum install -y libXext.x86_64 &&\
yum groupinstall -y "X Window System" &&\
cd /tmp &&\
wget https://iweb.dl.sourceforge.net/project/openofficeorg.mirror/4.1.6/binaries/zh-CN/Apache_OpenOffice_4.1.6_Linux_x86-64_install-rpm_zh-CN.tar.gz -cO openoffice_rpm.tar.gz &&\
tar zxf /tmp/openoffice_rpm.tar.gz &&\
cd /tmp/zh-CN/RPMS &&\
rpm -Uvih *.rpm &&\
rpm -Uvih desktop-integration/openoffice4.1.6-redhat-menus-4.1.6-9790.noarch.rpm &&\
rm -f /tmp/openoffice_rpm.tar.gz &&\
rm -rf /tmp/zh-CN &&\
cd /usr/share/fonts/chienes &&\
mkfontscale &&\
mkfontdir &&\
fc-cache -fv
ENV LANG zh_CN.UTF-8
ENV LC_ALL zh_CN.UTF-8
ENV KKFILEVIEW_BIN_FOLDER /opt/kkFileView-2.2.0-SNAPSHOT/bin
ENTRYPOINT ["java","-Dfile.encoding=UTF-8","-Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider","-Dspring.config.location=/opt/kkFileView-2.2.0-SNAPSHOT/config/application.properties","-jar","/opt/kkFileView-2.2.0-SNAPSHOT/bin/kkFileView-2.2.0-SNAPSHOT.jar"]

View File

@@ -57,29 +57,27 @@ Considering space issues, the pictures of other types of documents will not be s
- Redisson
- Jodconverter
> Dependencies
- Redis
- OpenOffice or LibreOffice
- Redis(Optional, Unnecessary by default)
- OpenOffice or LibreOffice(Integrated on Windows, will be installed automatically on Linux, need to be manually installed on Mac OS)
1. First step`git pull https://github.com/kekingcn/file-online-preview.git`
2. Second stepconfigure redis address and OpenOffice directorysuch as
```
#=============================================#Spring Redisson Configuration#===================================#
spring.redisson.address = 192.168.1.204:6379
##The folder for files which are uploaded to the server(Because of running as jar)
file.dir = C:\\Users\\yudian\\Desktop\\dev\\
## openoffice configuration
office.home = C:\\Program Files (x86)\\OpenOffice 4
```
'file.dir' is the real storage address of the converted files, please end with '/'.
3. Third stepRun the main method of FilePreviewApplication.java.After starting,visit `http://localhost:8012/`.
2. Third stepRun the main method of FilePreviewApplication.java.After starting,visit `http://localhost:8012/`.
If everything is ok,you will see the picture below.
![输入图片说明](https://gitee.com/uploads/images/2017/1213/100221_ea15202e_492218.png "屏幕截图.png")
### Changelog
> June 18th 2019
1. Support automatic cleaning of cache and preview files
2. Support http/https stream url file preview
3. Support FTP url file preview
4. Add Docker build
> April 8th 2019
1. Cache and queue implementations abstract, providing JDK and REDIS implementations (REDIS becomes optional dependencies)
2. Provides zip and tar.gz packages, and provides a one-click startup script
> January 17th 2018
1. Refined the project directory, abstract file preview interface, Easy to extend more file extensions and depoly this project on your own

View File

@@ -17,6 +17,7 @@
地址http://file.keking.cn/
### 项目文档Project documentation
1. 详细wiki文档https://gitee.com/kekingcn/file-online-preview/wikis/pages
1. 中文文档https://gitee.com/kekingcn/file-online-preview/blob/master/README.md
1. English documenthttps://github.com/kekingcn/kkFileView/blob/master/README.en.md
@@ -50,29 +51,27 @@ QQ群号613025121
- redisson
- jodconverter
> 依赖外部环境
- redis
- OpenOffice或者LibreOffice
- redis (可选,默认不用)
- OpenOffice或者LibreOffice(Windows下已内置Linux会自动安装Mac OS下需要手动安装)
1. 第一步pull项目https://github.com/kekingcn/file-online-preview.git
2. 第二步:配置redis地址和OpenOffice目录
```
#=============================================#spring Redisson配置#===================================#
spring.redisson.address = 192.168.1.204:6379
##资源映射路径(因为jar方式运行的原因)
file.dir = C:\\Users\\yudian\\Desktop\\dev\\
## openoffice相关配置
office.home = C:\\Program Files (x86)\\OpenOffice 4
```
file.dir为转换文件实际存储地址注意要以/结尾
3. 第三步运行FilePreviewApplication的main方法服务启动后访问http://localhost:8012/
3. 第二步:运行FilePreviewApplication的main方法服务启动后访问http://localhost:8012/
会看到如下界面,代表服务启动成功
![输入图片说明](https://gitee.com/uploads/images/2017/1213/100221_ea15202e_492218.png "屏幕截图.png")
### 历史更新记录
> 2019年06月18日
1. 支持自动清理缓存及预览文件
2. 支持http/https下载流url文件预览
3. 支持FTP url文件预览
4. 加入Docker构建
> 2019年04月08日
1. 缓存及队列实现抽象提供JDK和REDIS两种实现(REDIS成为可选依赖)
2. 打包方式提供zip和tar.gz包并提供一键启动脚本
> 2018年01月19日
1. 大文件入队提前处理

0
fonts/.gitkeep Normal file
View File

View File

@@ -12,8 +12,12 @@
//
package org.artofsolving.jodconverter.office;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import org.artofsolving.jodconverter.util.PlatformUtils;
@@ -23,6 +27,8 @@ import com.sun.star.uno.UnoRuntime;
public class OfficeUtils {
public static final String SERVICE_DESKTOP = "com.sun.star.frame.Desktop";
public static final String OFFICE_HOME_KEY = "office.home";
public static final String DEFAULT_OFFICE_HOME_VALUE = "default";
private OfficeUtils() {
throw new AssertionError("utility class must not be instantiated");
@@ -61,29 +67,42 @@ public class OfficeUtils {
}
public static File getDefaultOfficeHome() {
if (System.getProperty("office.home") != null) {
return new File(System.getProperty("office.home"));
Properties properties = new Properties();
String customizedConfigPath = getCustomizedConfigPath();
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(customizedConfigPath));
properties.load(bufferedReader);
restorePropertiesFromEnvFormat(properties);
} catch (Exception e) {}
String officeHome = properties.getProperty(OFFICE_HOME_KEY);
if (officeHome != null && !DEFAULT_OFFICE_HOME_VALUE.equals(officeHome)) {
return new File(officeHome);
}
if (PlatformUtils.isWindows()) {
// %ProgramFiles(x86)% on 64-bit machines; %ProgramFiles% on 32-bit ones
String homePath = OfficeUtils.getHomePath();
String programFiles = System.getenv("ProgramFiles(x86)");
if (programFiles == null) {
programFiles = System.getenv("ProgramFiles");
}
return findOfficeHome(
programFiles + File.separator + "OpenOffice 4",
programFiles + File.separator + "LibreOffice 4"
programFiles + File.separator + "LibreOffice 4",
homePath + File.separator + "office"
);
} else if (PlatformUtils.isMac()) {
return findOfficeHome(
"/Applications/OpenOffice.org.app/Contents",
"/Applications/OpenOffice.app/Contents",
"/Applications/LibreOffice.app/Contents"
);
} else {
// Linux or other *nix variants
return findOfficeHome(
"/opt/openoffice.org3",
"/opt/openoffice",
"/opt/libreoffice",
"/opt/openoffice4",
"/usr/lib/openoffice",
"/usr/lib/libreoffice"
);
@@ -102,10 +121,63 @@ public class OfficeUtils {
public static File getOfficeExecutable(File officeHome) {
if (PlatformUtils.isMac()) {
return new File(officeHome, "MacOS/soffice.bin");
return new File(officeHome, "MacOS/soffice");
} else {
return new File(officeHome, "program/soffice.bin");
}
}
public static String getHomePath() {
String userDir = System.getenv("KKFILEVIEW_BIN_FOLDER");
if (userDir == null) {
userDir = System.getProperty("user.dir");
}
if (userDir.endsWith("bin")) {
userDir = userDir.substring(0, userDir.length() - 4);
} else {
String separator = File.separator;
if (userDir.contains("jodconverter-web")) {
userDir = userDir + separator + "src" + separator + "main";
} else {
userDir = userDir + separator + "jodconverter-web" + separator + "src" + separator + "main";
}
}
return userDir;
}
public static String getCustomizedConfigPath() {
String homePath = OfficeUtils.getHomePath();
String separator = java.io.File.separator;
String configFilePath = homePath + separator + "config" + separator + "application.properties";
return configFilePath;
}
/**
* SpringBoot application.properties 支持从环境变量获取值
* @param properties
*/
public synchronized static void restorePropertiesFromEnvFormat(Properties properties) {
Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Object, Object> entry = iterator.next();
String key = entry.getKey().toString();
String value = entry.getValue().toString();
if (value.trim().startsWith("${") && value.trim().endsWith("}")) {
int beginIndex = value.indexOf(":");
if (beginIndex < 0) {
beginIndex = value.length() - 1;
}
int endIndex = value.length() - 1;
String envKey = value.substring(2, beginIndex);
String envValue = System.getenv(envKey);
if (envValue == null || "".equals(envValue.trim())) {
value = value.substring(beginIndex + 1, endIndex);
} else {
value = envValue;
}
properties.setProperty(key, value);
}
}
}
}

View File

@@ -10,7 +10,9 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jodconverter-web</artifactId>
<groupId>cn.keking</groupId>
<artifactId>kkFileView</artifactId>
<version>2.2.0-SNAPSHOT</version>
<properties>
@@ -104,13 +106,19 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.9</version>
<version>1.18</version>
</dependency>
<!-- 解压(rar)-->
<dependency>
<groupId>com.github.junrar</groupId>
<artifactId>junrar</artifactId>
<version>0.7</version>
<version>4.0.0</version>
</dependency>
<!-- 解压(7z)-->
<dependency>
<groupId>org.tukaani</groupId>
<artifactId>xz</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jchardet</groupId>
@@ -139,16 +147,42 @@
<artifactId>commons-cli</artifactId>
<version>1.2</version>
</dependency>
<!-- FTP -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
<version>1.4.6</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
<version>1.4.2</version>
</dependency>
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>5.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.15</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.15</version>
</dependency>
</dependencies>
<build>
<resources>
@@ -159,12 +193,36 @@
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/config</directory>
<excludes>
<exclude>${build.exclude.resource}</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@@ -0,0 +1,49 @@
<?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>
<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/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>src/main/office</directory>
<outputDirectory>${file.separator}office</outputDirectory>
</fileSet>
<fileSet>
<directory>${project.build.directory}</directory>
<outputDirectory>${file.separator}bin</outputDirectory>
<includes>
<include>*.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,36 @@
#!/bin/bash
cd /tmp
install_redhat() {
wget https://iweb.dl.sourceforge.net/project/openofficeorg.mirror/4.1.6/binaries/zh-CN/Apache_OpenOffice_4.1.6_Linux_x86-64_install-rpm_zh-CN.tar.gz -cO openoffice_rpm.tar.gz && tar zxf /tmp/openoffice_rpm.tar.gz && cd /tmp/zh-CN/RPMS
if [ $? -eq 0 ];then
rpm -Uvih *.rpm
echo 'install desktop service ...'
rpm -Uvih desktop-integration/openoffice4.1.6-redhat-menus-4.1.6-9790.noarch.rpm
echo 'install finshed...'
else
echo 'download package error...'
fi
}
install_ubuntu() {
wget https://iweb.dl.sourceforge.net/project/openofficeorg.mirror/4.1.6/binaries/zh-CN/Apache_OpenOffice_4.1.6_Linux_x86-64_install-deb_zh-CN.tar.gz -cO openoffice_deb.tar.gz && tar zxf /tmp/openoffice_deb.tar.gz && cd /tmp/zh-CN/DEBS
echo $?
if [ $? -eq 0 ];then
dpkg -i *.deb
echo 'install desktop service ...'
dpkg -i desktop-integration/openoffice4.1-debian-menus_4.1.6-9790_all.deb
echo 'install finshed...'
else
echo 'download package error...'
fi
}
if [ -f "/etc/redhat-release" ]; then
yum install -y wget
install_redhat
else
apt-get install -y wget
install_ubuntu
fi

View File

@@ -0,0 +1,2 @@
#!/bin/bash
tail -fn 300 ../log/kkFileView.log

View File

@@ -0,0 +1,2 @@
#!/bin/bash
kill -15 `ps -ef|grep kkFileView|awk 'NR==1{print $2}'`

View File

@@ -0,0 +1,9 @@
@echo off
set "KKFILEVIEW_BIN_FOLDER=%cd%"
cd "%KKFILEVIEW_BIN_FOLDER%"
echo Using KKFILEVIEW_BIN_FOLDER %KKFILEVIEW_BIN_FOLDER%
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 -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider -Dspring.config.location=..\config\application.properties -jar kkFileView-2.2.0-SNAPSHOT.jar -> ..\log\kkFileView.log

View File

@@ -0,0 +1,32 @@
#!/bin/bash
DIR_HOME=("/opt/openoffice.org3" "/opt/libreoffice" "/opt/openoffice4" "/usr/lib/openoffice" "/usr/lib/libreoffice")
FLAG=
OFFICE_HOME=
KKFILEVIEW_BIN_FOLDER=$(cd "$(dirname "$0")";pwd)
export KKFILEVIEW_BIN_FOLDER=$KKFILEVIEW_BIN_FOLDER
cd $KKFILEVIEW_BIN_FOLDER
echo "Using KKFILEVIEW_BIN_FOLDER $KKFILEVIEW_BIN_FOLDER"
grep 'office\.home' ../config/application.properties | grep '!^#'
if [ $? -eq 0 ]; then
echo "Using customized office.home"
else
for i in ${DIR_HOME[@]}
do
if [ -f $i"/program/soffice.bin" ]; then
FLAG=true
OFFICE_HOME=${i}
break
fi
done
if [ ! -n "${FLAG}" ]; then
echo "Installing OpenOffice"
sh ./install.sh
else
echo "Detected office component has been installed in $OFFICE_HOME"
fi
fi
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 -Dsun.java2d.cmm=sun.java2d.cmm.kcms.KcmsServiceProvider -Dspring.config.location=../config/application.properties -jar kkFileView-2.2.0-SNAPSHOT.jar > ../log/kkFileView.log 2>&1 &

View File

@@ -0,0 +1,57 @@
#######################################不可动态配置,需要重启生效#######################################
server.port = ${KK_SERVER_PORT:8012}
spring.http.encoding.charset = utf8
## Freemarker 配置
spring.freemarker.template-loader-path = classpath:/web/
spring.freemarker.cache = false
spring.freemarker.charset = UTF-8
spring.freemarker.check-template-location = true
spring.freemarker.content-type = text/html
spring.freemarker.expose-request-attributes = true
spring.freemarker.expose-session-attributes = true
spring.freemarker.request-context-attribute = request
spring.freemarker.suffix = .ftl
server.tomcat.uri-encoding = UTF-8
#文件上传限制
spring.http.multipart.max-request-size=100MB
spring.http.multipart.max-file-size=100MB
#文件资源路径默认为打包根路径下的file目录下
#file.dir = D:\\kkFileview\\
file.dir = ${KK_FILE_DIR:default}
#openoffice home路径
#office.home = C:\\Program Files (x86)\\OpenOffice 4
office.home = ${KK_OFFICE_HOME:default}
#缓存实现类型不配默认为内嵌RocksDB(type = default)实现可配置为redis(type = redis)实现需要配置spring.redisson.address等参数和 JDK 内置对象实现type = jdk,
cache.type = ${KK_CACHE_TYPE:default}
#redis连接只有当cache.type = redis时才有用
spring.redisson.address = ${KK_SPRING_REDISSON_ADDRESS:127.0.0.1:6379}
spring.redisson.password = ${KK_SPRING_REDISSON_PASSWORD:123456}
#缓存是否自动清理 true 为开启,注释掉或其他值都为关闭
cache.clean.enabled = ${KK_CACHE_CLEAN_ENABLED:true}
#缓存自动清理时间cache.clean.enabled = true时才有用cron表达式基于Quartz cron
cache.clean.cron = ${KK_CACHE_CLEAN_CRON:0 0 3 * * ?}
#######################################可在运行时动态配置#######################################
#提供预览服务的地址默认从请求url读如果使用nginx等反向代理需要手动设置
#base.url = https://file.keking.cn
base.url = ${KK_BASE_URL:default}
#是否启用缓存
cache.enabled = ${KK_CACHE_ENABLED:true}
#文本类型,默认如下,可自定义添加
simText = ${KK_SIMTEXT:txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd}
#多媒体类型,默认如下,可自定义添加
media = ${KK_MEDIA:mp3,wav,mp4,flv}
#office类型文档(word ppt)样式,默认为图片(image)可配置为pdf预览时也有按钮切换
office.preview.type = ${KK_OFFICE_PREVIEW_TYPE:image}
#预览源为FTP时 FTP用户名可在ftp url后面加参数ftp.username=ftpuser指定不指定默认用配置的
ftp.username = ${KK_FTP_USERNAME:ftpuser}
#预览源为FTP时 FTP密码可在ftp url后面加参数ftp.password=123456指定不指定默认用配置的
ftp.password = ${KK_FTP_PASSWORD:123456}
#预览源为FTP时, FTP连接默认ControlEncoding(根据FTP服务器操作系统选择Linux一般为UTF-8Windows一般为GBK)可在ftp url后面加参数ftp.control.encoding=UTF-8指定不指定默认用配置的
ftp.control.encoding = ${KK_FTP_CONTROL_ENCODING:UTF-8}

View File

@@ -0,0 +1,107 @@
package cn.keking.config;
import org.artofsolving.jodconverter.office.OfficeUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
/**
* @auther: chenjh
* @time: 2019/4/10 17:22
* @description
*/
@Component
public class ConfigConstants {
private static Boolean cacheEnabled;
private static String[] simText = {};
private static String[] media = {};
private static String officePreviewType;
private static String ftpUsername;
private static String ftpPassword;
private static String ftpControlEncoding;
private static String fileDir = OfficeUtils.getHomePath() + File.separator + "file" + File.separator;
private static String baseUrl;
public static final String DEFAULT_FILE_DIR_VALUE = "default";
public static Boolean isCacheEnabled() {
return cacheEnabled;
}
public static void setCacheEnabled(Boolean cacheEnabled) {
ConfigConstants.cacheEnabled = cacheEnabled;
}
public static String[] getSimText() {
return simText;
}
public static void setSimText(String[] simText) {
ConfigConstants.simText = simText;
}
public static String[] getMedia() {
return media;
}
public static void setMedia(String[] media) {
ConfigConstants.media = media;
}
public static String getOfficePreviewType() {
return officePreviewType;
}
public static void setOfficePreviewType(String officePreviewType) {
ConfigConstants.officePreviewType = officePreviewType;
}
public static String getFtpUsername() {
return ftpUsername;
}
public static void setFtpUsername(String ftpUsername) {
ConfigConstants.ftpUsername = ftpUsername;
}
public static String getFtpPassword() {
return ftpPassword;
}
public static String getFtpControlEncoding() {
return ftpControlEncoding;
}
public static void setFtpControlEncoding(String ftpControlEncoding) {
ConfigConstants.ftpControlEncoding = ftpControlEncoding;
}
public static void setFtpPassword(String ftpPassword) {
ConfigConstants.ftpPassword = ftpPassword;
}
public static String getFileDir() {
return fileDir;
}
public static String getBaseUrl() {
return baseUrl;
}
public static void setBaseUrl(String baseUrl) {
ConfigConstants.baseUrl = baseUrl;
}
@Value("${file.dir:default}")
public void setFileDir(String fileDir) {
if (!DEFAULT_FILE_DIR_VALUE.equals(fileDir.toLowerCase())) {
if (!fileDir.endsWith(File.separator)) {
fileDir = fileDir + File.separator;
}
ConfigConstants.fileDir = fileDir;
}
}
}

View File

@@ -0,0 +1,88 @@
package cn.keking.config;
import cn.keking.service.impl.OfficeFilePreviewImpl;
import org.artofsolving.jodconverter.office.OfficeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
* @auther: chenjh
* @time: 2019/4/10 16:16
* @description 每隔1s读取并更新一次配置文件
*/
@Component
public class ConfigRefreshComponent {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigRefreshComponent.class);
public static final String DEFAULT_CACHE_ENABLED = "true";
public static final String DEFAULT_TXT_TYPE = "txt,html,htm,asp,jsp,xml,json,properties,md,gitignore,,java,py,c,cpp,sql,sh,bat,m,bas,prg,cmd";
public static final String DEFAULT_MEDIA_TYPE = "mp3,wav,mp4,flv";
public static final String DEFAULT_FTP_USERNAME = null;
public static final String DEFAULT_FTP_PASSWORD = null;
public static final String DEFAULT_FTP_CONTROL_ENCODING = "UTF-8";
public static final String DEFAULT_BASE_URL = "default";
@PostConstruct
void refresh() {
Thread configRefreshThread = new Thread(new ConfigRefreshThread());
configRefreshThread.start();
}
class ConfigRefreshThread implements Runnable {
@Override
public void run() {
try {
Properties properties = new Properties();
String text;
String media;
Boolean cacheEnabled;
String[] textArray;
String[] mediaArray;
String officePreviewType;
String ftpUsername;
String ftpPassword;
String ftpControlEncoding;
String configFilePath = OfficeUtils.getCustomizedConfigPath();
String baseUlr;
while (true) {
FileReader fileReader = new FileReader(configFilePath);
BufferedReader bufferedReader = new BufferedReader(fileReader);
properties.load(bufferedReader);
OfficeUtils.restorePropertiesFromEnvFormat(properties);
cacheEnabled = new Boolean(properties.getProperty("cache.enabled", DEFAULT_CACHE_ENABLED));
text = properties.getProperty("simText", DEFAULT_TXT_TYPE);
media = properties.getProperty("media", DEFAULT_MEDIA_TYPE);
officePreviewType = properties.getProperty("office.preview.type", OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE);
ftpUsername = properties.getProperty("ftp.username", DEFAULT_FTP_USERNAME);
ftpPassword = properties.getProperty("ftp.password", DEFAULT_FTP_PASSWORD);
ftpControlEncoding = properties.getProperty("ftp.control.encoding", DEFAULT_FTP_CONTROL_ENCODING);
textArray = text.split(",");
mediaArray = media.split(",");
baseUlr = properties.getProperty("base.url", DEFAULT_BASE_URL);
ConfigConstants.setCacheEnabled(cacheEnabled);
ConfigConstants.setSimText(textArray);
ConfigConstants.setMedia(mediaArray);
ConfigConstants.setOfficePreviewType(officePreviewType);
ConfigConstants.setFtpUsername(ftpUsername);
ConfigConstants.setFtpPassword(ftpPassword);
ConfigConstants.setFtpControlEncoding(ftpControlEncoding);
ConfigConstants.setBaseUrl(baseUlr);
bufferedReader.close();
fileReader.close();
Thread.sleep(1000L);
}
} catch (IOException | InterruptedException e) {
LOGGER.error("读取配置文件异常", e);
}
}
}
}

View File

@@ -1,10 +1,9 @@
package cn.keking.config;
import io.netty.channel.nio.NioEventLoopGroup;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.Codec;
import org.redisson.config.Config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -14,6 +13,7 @@ import org.springframework.util.ClassUtils;
* Created by kl on 2017/09/26.
* redisson 客户端配置
*/
@ConditionalOnExpression("'${cache.type:default}'.equals('redis')")
@ConfigurationProperties(prefix = "spring.redisson")
@Configuration
public class RedissonConfig {
@@ -42,8 +42,8 @@ public class RedissonConfig {
private String codec="org.redisson.codec.JsonJacksonCodec";
@Bean(destroyMethod = "shutdown")
RedissonClient redisson() throws Exception {
@Bean
Config config() throws Exception {
Config config = new Config();
config.useSingleServer().setAddress(address)
.setConnectionMinimumIdleSize(connectionMinimumIdleSize)
@@ -69,7 +69,7 @@ public class RedissonConfig {
config.setThreads(thread);
config.setEventLoopGroup(new NioEventLoopGroup());
config.setUseLinuxNativeEpoll(false);
return Redisson.create(config);
return config;
}
public int getThread() {

View File

@@ -0,0 +1,28 @@
package cn.keking.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @auther: chenjh
* @time: 2019/4/16 20:04
* @description
*/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
private final static Logger LOGGER = LoggerFactory.getLogger(WebConfig.class);
/**
* 访问外部文件配置
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String filePath = ConfigConstants.getFileDir();
LOGGER.info("Add resource locations: {}", filePath);
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/","classpath:/resources/","classpath:/static/","classpath:/public/","file:" + filePath);
super.addResourceHandlers(registry);
}
}

View File

@@ -1,5 +1,8 @@
package cn.keking.filters;
import cn.keking.config.ConfigConstants;
import cn.keking.config.ConfigRefreshComponent;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@@ -19,10 +22,20 @@ public class ChinesePathFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(request.getScheme()).append("://").append(request.getServerName()).append(":")
.append(request.getServerPort()).append(((HttpServletRequest)request).getContextPath()).append("/");
request.setAttribute("baseUrl", pathBuilder.toString());
String baseUrl;
String baseUrlTmp = ConfigConstants.getBaseUrl();
if (baseUrlTmp != null && !ConfigRefreshComponent.DEFAULT_BASE_URL.equals(baseUrlTmp.toLowerCase())) {
if (!baseUrlTmp.endsWith("/")) {
baseUrlTmp = baseUrlTmp.concat("/");
}
baseUrl = baseUrlTmp;
} else {
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(request.getScheme()).append("://").append(request.getServerName()).append(":")
.append(request.getServerPort()).append(((HttpServletRequest) request).getContextPath()).append("/");
baseUrl = pathBuilder.toString();
}
request.setAttribute("baseUrl", baseUrl);
chain.doFilter(request, response);
}

View File

@@ -2,9 +2,8 @@ package cn.keking.service;
import cn.keking.model.FileAttribute;
import cn.keking.model.FileType;
import cn.keking.service.cache.CacheService;
import cn.keking.utils.FileUtils;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -28,7 +27,7 @@ public class FileConverQueueTask {
FilePreviewFactory previewFactory;
@Autowired
RedissonClient redissonClient;
CacheService cacheService;
@Autowired
FileUtils fileUtils;
@@ -36,7 +35,7 @@ public class FileConverQueueTask {
@PostConstruct
public void startTask(){
ExecutorService executorService = Executors.newFixedThreadPool(3);
executorService.submit(new ConverTask(previewFactory,redissonClient,fileUtils));
executorService.submit(new ConverTask(previewFactory, cacheService, fileUtils));
logger.info("队列处理文件转换任务启动完成 ");
}
@@ -44,13 +43,13 @@ public class FileConverQueueTask {
FilePreviewFactory previewFactory;
RedissonClient redissonClient;
CacheService cacheService;
FileUtils fileUtils;
public ConverTask(FilePreviewFactory previewFactory, RedissonClient redissonClient,FileUtils fileUtils) {
public ConverTask(FilePreviewFactory previewFactory, CacheService cacheService, FileUtils fileUtils) {
this.previewFactory = previewFactory;
this.redissonClient = redissonClient;
this.cacheService = cacheService;
this.fileUtils=fileUtils;
}
@@ -58,15 +57,14 @@ public class FileConverQueueTask {
public void run() {
while (true) {
try {
final RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName);
String url = queue.take();
if(url!=null){
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
String url = cacheService.takeQueueTask();
if(url != null){
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
logger.info("正在处理转换任务,文件名称【{}】",fileAttribute.getName());
FileType fileType=fileAttribute.getType();
if(fileType.equals(FileType.compress) || fileType.equals(FileType.office)){
FilePreview filePreview=previewFactory.get(url);
filePreview.filePreviewHandle(url,new ExtendedModelMap());
FilePreview filePreview=previewFactory.get(fileAttribute);
filePreview.filePreviewHandle(url, new ExtendedModelMap(), fileAttribute);
}
}
} catch (Exception e) {

View File

@@ -1,5 +1,6 @@
package cn.keking.service;
import cn.keking.model.FileAttribute;
import org.springframework.ui.Model;
/**
@@ -7,5 +8,5 @@ import org.springframework.ui.Model;
* Content :
*/
public interface FilePreview {
String filePreviewHandle(String url, Model model);
String filePreviewHandle(String url, Model model, FileAttribute fileAttribute);
}

View File

@@ -5,7 +5,6 @@ import cn.keking.utils.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import java.util.Map;
@@ -22,9 +21,8 @@ public class FilePreviewFactory {
@Autowired
ApplicationContext context;
public FilePreview get(String url) {
public FilePreview get(FileAttribute fileAttribute) {
Map<String, FilePreview> filePreviewMap = context.getBeansOfType(FilePreview.class);
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
return filePreviewMap.get(fileAttribute.getType().getInstanceName());
}
}

View File

@@ -0,0 +1,40 @@
package cn.keking.service.cache;
import java.util.List;
import java.util.Map;
/**
* @auther: chenjh
* @time: 2019/4/2 16:45
* @description
*/
public interface CacheService {
final String REDIS_FILE_PREVIEW_PDF_KEY = "converted-preview-pdf-file";
final String REDIS_FILE_PREVIEW_IMGS_KEY = "converted-preview-imgs-file";//压缩包内图片文件集合
final String REDIS_FILE_PREVIEW_PDF_IMGS_KEY = "converted-preview-pdfimgs-file";
final Integer DEFAULT_PDF_CAPACITY = 500000;
final Integer DEFAULT_IMG_CAPACITY = 500000;
final Integer DEFAULT_PDFIMG_CAPACITY = 500000;
void initPDFCachePool(Integer capacity);
void initIMGCachePool(Integer capacity);
void initPdfImagesCachePool(Integer capacity);
void putPDFCache(String key, String value);
void putImgCache(String key, List<String> value);
Map<String, String> getPDFCache();
String getPDFCache(String key);
Map<String, List<String>> getImgCache();
List<String> getImgCache(String key);
Integer getPdfImageCache(String key);
void putPdfImageCache(String pdfFilePath, int num);
void cleanCache();
void addQueueTask(String url);
String takeQueueTask() throws InterruptedException;
}

View File

@@ -0,0 +1,135 @@
package cn.keking.service.cache.impl;
import cn.keking.service.cache.CacheService;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.Weighers;
import org.rocksdb.RocksDB;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* @auther: chenjh
* @time: 2019/4/2 17:21
* @description
*/
@Service
@ConditionalOnExpression("'${cache.type:default}'.equals('jdk')")
public class CacheServiceJDKImpl implements CacheService {
private Map<String, String> pdfCache;
private Map<String, List<String>> imgCache;
private Map<String, Integer> pdfImagesCache;
private static final int QUEUE_SIZE = 500000;
private BlockingQueue blockingQueue = new ArrayBlockingQueue(QUEUE_SIZE);
@Override
public void initPDFCachePool(Integer capacity) {
pdfCache = new ConcurrentLinkedHashMap.Builder<String, String>()
.maximumWeightedCapacity(capacity).weigher(Weighers.singleton())
.build();
}
@Override
public void initIMGCachePool(Integer capacity) {
imgCache = new ConcurrentLinkedHashMap.Builder<String, List<String>>()
.maximumWeightedCapacity(capacity).weigher(Weighers.singleton())
.build();
}
@Override
public void initPdfImagesCachePool(Integer capacity) {
pdfImagesCache = new ConcurrentLinkedHashMap.Builder<String, Integer>()
.maximumWeightedCapacity(capacity).weigher(Weighers.singleton())
.build();
}
@Override
public void putPDFCache(String key, String value) {
if (pdfCache == null) {
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
}
pdfCache.put(key, value);
}
@Override
public void putImgCache(String key, List<String> value) {
if (imgCache == null) {
initIMGCachePool(CacheService.DEFAULT_IMG_CAPACITY);
}
imgCache.put(key, value);
}
@Override
public Map<String, String> getPDFCache() {
if (pdfCache == null) {
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
}
return pdfCache;
}
@Override
public String getPDFCache(String key) {
if (pdfCache == null) {
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
}
return pdfCache.get(key);
}
@Override
public Map<String, List<String>> getImgCache() {
if (imgCache == null) {
initPDFCachePool(CacheService.DEFAULT_IMG_CAPACITY);
}
return imgCache;
}
@Override
public List<String> getImgCache(String key) {
if (imgCache == null) {
initPDFCachePool(CacheService.DEFAULT_IMG_CAPACITY);
}
return imgCache.get(key);
}
@Override
public Integer getPdfImageCache(String key) {
if (pdfImagesCache == null) {
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
}
return pdfImagesCache.get(key);
}
@Override
public void putPdfImageCache(String pdfFilePath, int num) {
if (pdfImagesCache == null) {
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
}
pdfImagesCache.put(pdfFilePath, num);
}
@Override
public void cleanCache() {
initPDFCachePool(CacheService.DEFAULT_PDF_CAPACITY);
initIMGCachePool(CacheService.DEFAULT_IMG_CAPACITY);
initPdfImagesCachePool(CacheService.DEFAULT_PDFIMG_CAPACITY);
}
@Override
public void addQueueTask(String url) {
blockingQueue.add(url);
}
@Override
public String takeQueueTask() throws InterruptedException {
return String.valueOf(blockingQueue.take());
}
}

View File

@@ -0,0 +1,130 @@
package cn.keking.service.cache.impl;
import cn.keking.service.FileConverQueueTask;
import cn.keking.service.cache.CacheService;
import org.redisson.Redisson;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* @auther: chenjh
* @time: 2019/4/2 18:02
* @description
*/
@ConditionalOnExpression("'${cache.type:default}'.equals('redis')")
@Service
public class CacheServiceRedisImpl implements CacheService {
private Config config;
@Autowired
public CacheServiceRedisImpl(Config config) {
this.config = config;
this.redissonClient = Redisson.create(config);
}
private RedissonClient redissonClient;
@Override
public void initPDFCachePool(Integer capacity) {
}
@Override
public void initIMGCachePool(Integer capacity) {
}
@Override
public void initPdfImagesCachePool(Integer capacity) {
}
@Override
public void putPDFCache(String key, String value) {
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
convertedList.fastPut(key, value);
}
@Override
public void putImgCache(String key, List<String> value) {
RMapCache<String, List<String>> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
convertedList.fastPut(key, value);
}
@Override
public Map<String, String> getPDFCache() {
return redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
}
@Override
public String getPDFCache(String key) {
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
return convertedList.get(key);
}
@Override
public Map<String, List<String>> getImgCache() {
return redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
}
@Override
public List<String> getImgCache(String key) {
RMapCache<String, List<String>> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
return convertedList.get(key);
}
@Override
public Integer getPdfImageCache(String key) {
RMapCache<String, Integer> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_IMGS_KEY);
return convertedList.get(key);
}
@Override
public void putPdfImageCache(String pdfFilePath, int num) {
RMapCache<String, Integer> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_IMGS_KEY);
convertedList.fastPut(pdfFilePath, num);
}
@Override
public void cleanCache() {
cleanPdfCache();
cleanImgCache();
cleanPdfImgCache();
}
@Override
public void addQueueTask(String url) {
RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName);
queue.addAsync(url);
}
@Override
public String takeQueueTask() throws InterruptedException {
RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName);
return queue.take();
}
private void cleanPdfCache() {
RMapCache<String, String> pdfCache = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
pdfCache.clear();
}
private void cleanImgCache() {
RMapCache<String, List<String>> imgCache = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
imgCache.clear();
}
private void cleanPdfImgCache() {
RMapCache<String, Integer> pdfImg = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_IMGS_KEY);
pdfImg.clear();
}
}

View File

@@ -0,0 +1,239 @@
package cn.keking.service.cache.impl;
import cn.keking.service.cache.CacheService;
import org.artofsolving.jodconverter.office.OfficeUtils;
import org.rocksdb.RocksDB;
import org.rocksdb.RocksDBException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Service;
import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
/**
* @auther: chenjh
* @time: 2019/4/22 11:02
* @description
*/
@ConditionalOnExpression("'${cache.type:default}'.equals('default')")
@Service
public class CacheServiceRocksDBImpl implements CacheService {
static {
RocksDB.loadLibrary();
}
private static final String DB_PATH = OfficeUtils.getHomePath() + File.separator + "cache";
private static final int QUEUE_SIZE = 500000;
private static final Logger LOGGER = LoggerFactory.getLogger(CacheServiceRocksDBImpl.class);
private BlockingQueue blockingQueue = new ArrayBlockingQueue(QUEUE_SIZE);
private RocksDB db;
{
try {
db = RocksDB.open(DB_PATH);
if (db.get(REDIS_FILE_PREVIEW_PDF_KEY.getBytes()) == null) {
Map<String, String> initPDFCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(initPDFCache));
}
if (db.get(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes()) == null) {
Map<String, List<String>> initIMGCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(initIMGCache));
}
if (db.get(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes()) == null) {
Map<String, Integer> initPDFIMGCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(initPDFIMGCache));
}
} catch (RocksDBException | IOException e) {
LOGGER.error("Uable to init RocksDB" + e);
}
}
@Override
public void initPDFCachePool(Integer capacity) {
}
@Override
public void initIMGCachePool(Integer capacity) {
}
@Override
public void initPdfImagesCachePool(Integer capacity) {
}
@Override
public void putPDFCache(String key, String value) {
try {
Map<String, String> pdfCacheItem = getPDFCache();
pdfCacheItem.put(key, value);
db.put(REDIS_FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(pdfCacheItem));
} catch (RocksDBException | IOException e) {
LOGGER.error("Put into RocksDB Exception" + e);
}
}
@Override
public void putImgCache(String key, List<String> value) {
try {
Map<String, List<String>> imgCacheItem = getImgCache();
imgCacheItem.put(key, value);
db.put(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(imgCacheItem));
} catch (RocksDBException | IOException e) {
LOGGER.error("Put into RocksDB Exception" + e);
}
}
@Override
public Map<String, String> getPDFCache() {
Map<String, String> result = new HashMap<>();
try{
result = (Map<String, String>) toObject(db.get(REDIS_FILE_PREVIEW_PDF_KEY.getBytes()));
} catch (RocksDBException | IOException | ClassNotFoundException e) {
LOGGER.error("Get from RocksDB Exception" + e);
}
return result;
}
@Override
public String getPDFCache(String key) {
String result = "";
try{
Map<String, String> map = (Map<String, String>) toObject(db.get(REDIS_FILE_PREVIEW_PDF_KEY.getBytes()));
result = map.get(key);
} catch (RocksDBException | IOException | ClassNotFoundException e) {
LOGGER.error("Get from RocksDB Exception" + e);
}
return result;
}
@Override
public Map<String, List<String>> getImgCache() {
Map<String, List<String>> result = new HashMap<>();
try{
result = (Map<String, List<String>>) toObject(db.get(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes()));
} catch (RocksDBException | IOException | ClassNotFoundException e) {
LOGGER.error("Get from RocksDB Exception" + e);
}
return result;
}
@Override
public List<String> getImgCache(String key) {
List<String> result = new ArrayList<>();
Map<String, List<String>> map;
try{
map = (Map<String, List<String>>) toObject(db.get(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes()));
result = map.get(key);
} catch (RocksDBException | IOException | ClassNotFoundException e) {
LOGGER.error("Get from RocksDB Exception" + e);
}
return result;
}
public Map<String, Integer> getPdfImageCaches() {
Map<String, Integer> map = new HashMap<>();
try{
map = (Map<String, Integer>) toObject(db.get(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes()));
} catch (RocksDBException | IOException | ClassNotFoundException e) {
LOGGER.error("Get from RocksDB Exception" + e);
}
return map;
}
@Override
public Integer getPdfImageCache(String key) {
Integer result = 0;
Map<String, Integer> map;
try{
map = (Map<String, Integer>) toObject(db.get(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes()));
result = map.get(key);
} catch (RocksDBException | IOException | ClassNotFoundException e) {
LOGGER.error("Get from RocksDB Exception" + e);
}
return result;
}
@Override
public void putPdfImageCache(String pdfFilePath, int num) {
try {
Map<String, Integer> pdfImageCacheItem = getPdfImageCaches();
pdfImageCacheItem.put(pdfFilePath, num);
db.put(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(pdfImageCacheItem));
} catch (RocksDBException | IOException e) {
LOGGER.error("Put into RocksDB Exception" + e);
}
}
@Override
public void cleanCache() {
try {
cleanPdfCache();
cleanImgCache();
cleanPdfImgCache();
} catch (IOException | RocksDBException e) {
LOGGER.error("Clean Cache Exception" + e);
}
}
@Override
public void addQueueTask(String url) {
blockingQueue.add(url);
}
@Override
public String takeQueueTask() throws InterruptedException {
return String.valueOf(blockingQueue.take());
}
private byte[] toByteArray (Object obj) throws IOException {
byte[] bytes = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
bytes = bos.toByteArray ();
oos.close();
bos.close();
return bytes;
}
private Object toObject (byte[] bytes) throws IOException, ClassNotFoundException {
Object obj = null;
ByteArrayInputStream bis = new ByteArrayInputStream (bytes);
ObjectInputStream ois = new ObjectInputStream (bis);
obj = ois.readObject();
ois.close();
bis.close();
return obj;
}
private void cleanPdfCache() throws IOException, RocksDBException {
Map<String, String> initPDFCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_PDF_KEY.getBytes(), toByteArray(initPDFCache));
}
private void cleanImgCache() throws IOException, RocksDBException {
Map<String, List<String>> initIMGCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_IMGS_KEY.getBytes(), toByteArray(initIMGCache));
}
private void cleanPdfImgCache() throws IOException, RocksDBException {
Map<String, Integer> initPDFIMGCache = new HashMap<>();
db.put(REDIS_FILE_PREVIEW_PDF_IMGS_KEY.getBytes(), toByteArray(initPDFIMGCache));
}
}

View File

@@ -1,5 +1,6 @@
package cn.keking.service.impl;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse;
import cn.keking.service.FilePreview;
@@ -28,16 +29,15 @@ public class CompressFilePreviewImpl implements FilePreview{
ZipReader zipReader;
@Override
public String filePreviewHandle(String url, Model model) {
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
String fileName=fileAttribute.getName();
String decodedUrl=fileAttribute.getDecodedUrl();
String suffix=fileAttribute.getSuffix();
String fileTree = null;
// 判断文件名是否存在(redis缓存读取)
if (!StringUtils.hasText(fileUtils.getConvertedFile(fileName))) {
ReturnResponse<String> response = downloadUtils.downLoad(decodedUrl, suffix, fileName);
if (!StringUtils.hasText(fileUtils.getConvertedFile(fileName)) || !ConfigConstants.isCacheEnabled()) {
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
if (0 != response.getCode()) {
model.addAttribute("fileType", suffix);
model.addAttribute("msg", response.getMsg());
return "fileNotSupported";
}
@@ -46,15 +46,20 @@ public class CompressFilePreviewImpl implements FilePreview{
fileTree = zipReader.readZipFile(filePath, fileName);
} else if ("rar".equalsIgnoreCase(suffix)) {
fileTree = zipReader.unRar(filePath, fileName);
} else if ("7z".equalsIgnoreCase(suffix)) {
fileTree = zipReader.read7zFile(filePath, fileName);
}
if (fileTree != null && !"null".equals(fileTree) && ConfigConstants.isCacheEnabled()) {
fileUtils.addConvertedFile(fileName, fileTree);
}
fileUtils.addConvertedFile(fileName, fileTree);
} else {
fileTree = fileUtils.getConvertedFile(fileName);
}
if (null != fileTree) {
if (fileTree != null && !"null".equals(fileTree)) {
model.addAttribute("fileTree", fileTree);
return "compress";
} else {
model.addAttribute("fileType", suffix);
model.addAttribute("msg", "压缩文件类型不受支持尝试在压缩的时候选择RAR4格式");
return "fileNotSupported";
}

View File

@@ -1,5 +1,6 @@
package cn.keking.service.impl;
import cn.keking.model.FileAttribute;
import cn.keking.service.FilePreview;
import cn.keking.utils.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -18,8 +19,12 @@ public class MediaFilePreviewImpl implements FilePreview {
FileUtils fileUtils;
@Override
public String filePreviewHandle(String url, Model model) {
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
model.addAttribute("mediaUrl", url);
String suffix=fileAttribute.getSuffix();
if ("flv".equalsIgnoreCase(suffix)) {
return "flv";
}
return "media";
}

View File

@@ -1,19 +1,20 @@
package cn.keking.service.impl;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse;
import cn.keking.service.FilePreview;
import cn.keking.utils.DownloadUtils;
import cn.keking.utils.FileUtils;
import cn.keking.utils.OfficeToPdf;
import cn.keking.utils.PdfUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.ui.ExtendedModelMap;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import java.io.File;
import java.util.List;
/**
* Created by kl on 2018/1/17.
@@ -25,8 +26,8 @@ public class OfficeFilePreviewImpl implements FilePreview {
@Autowired
FileUtils fileUtils;
@Value("${file.dir}")
String fileDir;
@Autowired
PdfUtils pdfUtils;
@Autowired
DownloadUtils downloadUtils;
@@ -34,38 +35,57 @@ public class OfficeFilePreviewImpl implements FilePreview {
@Autowired
private OfficeToPdf officeToPdf;
String fileDir = ConfigConstants.getFileDir();
public static final String OFFICE_PREVIEW_TYPE_PDF = "pdf";
public static final String OFFICE_PREVIEW_TYPE_IMAGE = "image";
public static final String OFFICE_PREVIEW_TYPE_ALLIMAGES = "allImages";
@Override
public String filePreviewHandle(String url, Model model) {
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
// 预览Type参数传了就取参数的没传取系统默认
String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString();
String originUrl = (String) model.asMap().get("originUrl");
String suffix=fileAttribute.getSuffix();
String fileName=fileAttribute.getName();
String decodedUrl=fileAttribute.getDecodedUrl();
boolean isHtml = suffix.equalsIgnoreCase("xls") || suffix.equalsIgnoreCase("xlsx");
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + (isHtml ? "html" : "pdf");
String outFilePath = fileDir + pdfName;
// 判断之前是否已转换过,如果转换过,直接返回,否则执行转换
if (!fileUtils.listConvertedFiles().containsKey(pdfName)) {
if (!fileUtils.listConvertedFiles().containsKey(pdfName) || !ConfigConstants.isCacheEnabled()) {
String filePath = fileDir + fileName;
if (!new File(filePath).exists()) {
ReturnResponse<String> response = downloadUtils.downLoad(decodedUrl, suffix, null);
if (0 != response.getCode()) {
model.addAttribute("msg", response.getMsg());
return "fileNotSupported";
}
filePath = response.getContent();
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, null);
if (0 != response.getCode()) {
model.addAttribute("fileType", suffix);
model.addAttribute("msg", response.getMsg());
return "fileNotSupported";
}
String outFilePath = fileDir + pdfName;
filePath = response.getContent();
if (StringUtils.hasText(outFilePath)) {
officeToPdf.openOfficeToPDF(filePath, outFilePath);
File f = new File(filePath);
if (f.exists()) {
f.delete();
}
if (isHtml) {
// 对转换后的文件进行操作(改变编码方式)
fileUtils.doActionConvertedFile(outFilePath);
}
// 加入缓存
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
if (ConfigConstants.isCacheEnabled()) {
// 加入缓存
fileUtils.addConvertedFile(pdfName, fileUtils.getRelativePath(outFilePath));
}
}
}
if (!isHtml && originUrl != null && (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OFFICE_PREVIEW_TYPE_ALLIMAGES.equals(officePreviewType))) {
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl);
if (imageUrls == null || imageUrls.size() < 1) {
model.addAttribute("msg", "office转图片异常请联系管理员");
model.addAttribute("fileType",fileAttribute.getSuffix());
return "fileNotSupported";
}
model.addAttribute("imgurls", imageUrls);
model.addAttribute("currentUrl", imageUrls.get(0));
if (OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType)) {
return "officePicture";
} else {
return "picture";
}
}
model.addAttribute("pdfUrl", pdfName);

View File

@@ -17,9 +17,7 @@ public class OtherFilePreviewImpl implements FilePreview {
FileUtils fileUtils;
@Override
public String filePreviewHandle(String url, Model model) {
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
model.addAttribute("fileType",fileAttribute.getSuffix());
model.addAttribute("msg", "系统还不支持该格式文件的在线预览," +
"如有需要请按下方显示的邮箱地址联系系统维护人员");

View File

@@ -1,9 +1,19 @@
package cn.keking.service.impl;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse;
import cn.keking.service.FilePreview;
import cn.keking.utils.DownloadUtils;
import cn.keking.utils.FileUtils;
import cn.keking.utils.PdfUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import java.io.File;
import java.util.List;
/**
* Created by kl on 2018/1/17.
* Content :处理pdf文件
@@ -11,9 +21,50 @@ import org.springframework.ui.Model;
@Service
public class PdfFilePreviewImpl implements FilePreview{
@Autowired
FileUtils fileUtils;
@Autowired
PdfUtils pdfUtils;
@Autowired
DownloadUtils downloadUtils;
String fileDir = ConfigConstants.getFileDir();
@Override
public String filePreviewHandle(String url, Model model) {
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
String suffix=fileAttribute.getSuffix();
String fileName=fileAttribute.getName();
String officePreviewType = model.asMap().get("officePreviewType") == null ? ConfigConstants.getOfficePreviewType() : model.asMap().get("officePreviewType").toString();
String originUrl = model.asMap().get("originUrl").toString();
model.addAttribute("pdfUrl", url);
String pdfName = fileName.substring(0, fileName.lastIndexOf(".") + 1) + "pdf";
String outFilePath = fileDir + pdfName;
if (OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType) || OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_ALLIMAGES.equals(officePreviewType)) {
//当文件不存在时,就去下载
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
if (0 != response.getCode()) {
model.addAttribute("fileType", suffix);
model.addAttribute("msg", response.getMsg());
return "fileNotSupported";
}
outFilePath = response.getContent();
List<String> imageUrls = pdfUtils.pdf2jpg(outFilePath, pdfName, originUrl);
if (imageUrls == null || imageUrls.size() < 1) {
model.addAttribute("msg", "pdf转图片异常请联系管理员");
model.addAttribute("fileType",fileAttribute.getSuffix());
return "fileNotSupported";
}
model.addAttribute("imgurls", imageUrls);
model.addAttribute("currentUrl", imageUrls.get(0));
if (OfficeFilePreviewImpl.OFFICE_PREVIEW_TYPE_IMAGE.equals(officePreviewType)) {
return "officePicture";
} else {
return "picture";
}
}
return "pdf";
}
}

View File

@@ -1,5 +1,6 @@
package cn.keking.service.impl;
import cn.keking.model.FileAttribute;
import cn.keking.service.FilePreview;
import cn.keking.utils.FileUtils;
import com.google.common.collect.Lists;
@@ -21,7 +22,7 @@ public class PictureFilePreviewImpl implements FilePreview {
FileUtils fileUtils;
@Override
public String filePreviewHandle(String url, Model model) {
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute) {
String fileKey=(String) RequestContextHolder.currentRequestAttributes().getAttribute("fileKey",0);
List imgUrls = Lists.newArrayList(url);
try{

View File

@@ -9,6 +9,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
/**
* Created by kl on 2018/1/17.
* Content :处理文本文件
@@ -23,8 +27,7 @@ public class SimTextFilePreviewImpl implements FilePreview{
FileUtils fileUtils;
@Override
public String filePreviewHandle(String url, Model model){
FileAttribute fileAttribute=fileUtils.getFileAttribute(url);
public String filePreviewHandle(String url, Model model, FileAttribute fileAttribute){
String decodedUrl=fileAttribute.getDecodedUrl();
String fileName=fileAttribute.getName();
ReturnResponse<String> response = simTextUtil.readSimText(decodedUrl, fileName);
@@ -33,7 +36,16 @@ public class SimTextFilePreviewImpl implements FilePreview{
model.addAttribute("fileType",fileAttribute.getSuffix());
return "fileNotSupported";
}
model.addAttribute("ordinaryUrl", response.getMsg());
try {
File originFile = new File(response.getContent());
File previewFile = new File(response.getContent() + ".txt");
Files.copy(originFile.toPath(), previewFile.toPath());
} catch (IOException e) {
model.addAttribute("msg", e.getLocalizedMessage());
model.addAttribute("fileType",fileAttribute.getSuffix());
return "fileNotSupported";
}
model.addAttribute("ordinaryUrl", response.getMsg() + ".txt");
return "txt";
}

View File

@@ -5,6 +5,7 @@ import cn.keking.extend.ControlDocumentFormatRegistry;
import org.artofsolving.jodconverter.OfficeDocumentConverter;
import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration;
import org.artofsolving.jodconverter.office.OfficeManager;
import org.artofsolving.jodconverter.office.OfficeUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@@ -23,8 +24,8 @@ import java.util.Map;
@Component
public class ConverterUtils {
@Value("${office.home}")
String officeHome;
// @Value("${office.home}")
// String officeHome;
// OpenOfficeConnection connection;
OfficeManager officeManager;
@@ -32,6 +33,7 @@ public class ConverterUtils {
public void initOfficeManager() {
//// connection = new SocketOpenOfficeConnection(host,8100);
//// connection.connect();
String officeHome = OfficeUtils.getDefaultOfficeHome().getAbsolutePath();
DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration();
configuration.setOfficeHome(officeHome);
configuration.setPortNumber(8100);

View File

@@ -1,8 +1,14 @@
package cn.keking.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
public class DeleteFileUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(DeleteFileUtil.class);
/**
* 删除单个文件
*
@@ -15,14 +21,14 @@ public class DeleteFileUtil {
// 如果文件路径所对应的文件存在,并且是一个文件,则直接删除
if (file.exists() && file.isFile()) {
if (file.delete()) {
System.out.println("删除单个文件" + fileName + "成功!");
LOGGER.info("删除单个文件" + fileName + "成功!");
return true;
} else {
System.out.println("删除单个文件" + fileName + "失败!");
LOGGER.info("删除单个文件" + fileName + "失败!");
return false;
}
} else {
System.out.println("删除单个文件失败:" + fileName + "不存在!");
LOGGER.info("删除单个文件失败:" + fileName + "不存在!");
return false;
}
}
@@ -43,7 +49,7 @@ public class DeleteFileUtil {
File dirFile = new File(dir);
// 如果dir对应的文件不存在或者不是一个目录则退出
if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
System.out.println("删除目录失败:" + dir + "不存在!");
LOGGER.info("删除目录失败:" + dir + "不存在!");
return false;
}
boolean flag = true;
@@ -65,7 +71,7 @@ public class DeleteFileUtil {
}
}
if (!flag) {
System.out.println("删除目录失败!");
LOGGER.info("删除目录失败!");
return false;
}
return true;

View File

@@ -1,7 +1,11 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse;
import org.springframework.beans.factory.annotation.Value;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.*;
import java.net.*;
@@ -13,8 +17,16 @@ import java.util.UUID;
@Component
public class DownloadUtils {
@Value("${file.dir}")
String fileDir;
private static final Logger LOGGER = LoggerFactory.getLogger(DownloadUtils.class);
private String fileDir = ConfigConstants.getFileDir();
@Autowired
private FileUtils fileUtils;
private static final String URL_PARAM_FTP_USERNAME = "ftp.username";
private static final String URL_PARAM_FTP_PASSWORD = "ftp.password";
private static final String URL_PARAM_FTP_CONTROL_ENCODING = "ftp.control.encoding";
/**
* 一开始测试的时候发现有些文件没有下载下来,而有些可以;当时也是郁闷了好一阵,但是最终还是不得解
@@ -22,18 +34,21 @@ public class DownloadUtils {
* 应该是转义出了问题url转义中会把+号当成空格来计算所以才会出现这种情况遂想要通过整体替换空格为加号因为url
* 中的参数部分是不会出现空格的但是文件名中就不好确定了所以只对url参数部分做替换
* 注: 针对URLEncoder.encode(s,charset)会将空格转成+的情况需要做下面的替换工作
* @param urlAddress
* @param type
* @param fileAttribute
* @return
*/
public ReturnResponse<String> downLoad(String urlAddress, String type, String fileName){
public ReturnResponse<String> downLoad(FileAttribute fileAttribute, String fileName) {
String urlAddress = fileAttribute.getDecodedUrl();
String type = fileAttribute.getSuffix();
ReturnResponse<String> response = new ReturnResponse<>(0, "下载成功!!!", "");
URL url = null;
try {
urlAddress = replacePlusMark(urlAddress);
urlAddress = encodeUrlParam(urlAddress);
// 因为tomcat不能处理'+'号,所以讲'+'号替换成'%20%'
// 也不能处理空格
urlAddress = urlAddress.replaceAll("\\+", "%20");
urlAddress = urlAddress.replaceAll(" ", "%20");
url = new URL(urlAddress);
} catch (MalformedURLException e) {
e.printStackTrace();
@@ -41,7 +56,7 @@ public class DownloadUtils {
UUID uuid = UUID.randomUUID();
if (null == fileName) {
fileName = uuid+ "."+type;
}else { // 文件后缀不一致时以type为准(针对simText【将类txt文件转为txt】)
} else { // 文件后缀不一致时以type为准(针对simText【将类txt文件转为txt】)
fileName = fileName.replace(fileName.substring(fileName.lastIndexOf(".") + 1), type);
}
String realPath = fileDir + fileName;
@@ -50,17 +65,24 @@ public class DownloadUtils {
dirFile.mkdirs();
}
try {
URLConnection connection = url.openConnection();
InputStream in = connection.getInputStream();
if ("ftp".equals(url.getProtocol())) {
String ftpUsername = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_USERNAME);
String ftpPassword = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_PASSWORD);
String ftpControlEncoding = fileUtils.getUrlParameterReg(fileAttribute.getUrl(), URL_PARAM_FTP_CONTROL_ENCODING);
FtpUtils.download(fileAttribute.getUrl(), realPath, ftpUsername, ftpPassword, ftpControlEncoding);
} else {
URLConnection connection = url.openConnection();
InputStream in = connection.getInputStream();
FileOutputStream os = new FileOutputStream(realPath);
byte[] buffer = new byte[4 * 1024];
int read;
while ((read = in.read(buffer)) > 0) {
os.write(buffer, 0, read);
FileOutputStream os = new FileOutputStream(realPath);
byte[] buffer = new byte[4 * 1024];
int read;
while ((read = in.read(buffer)) > 0) {
os.write(buffer, 0, read);
}
os.close();
in.close();
}
os.close();
in.close();
response.setContent(realPath);
// 同样针对类txt文件如果成功msg包含的是转换后的文件名
response.setMsg(fileName);
@@ -69,15 +91,14 @@ public class DownloadUtils {
if("txt".equals(type)){
convertTextPlainFileCharsetToUtf8(realPath);
}
return response;
} catch (IOException e) {
e.printStackTrace();
LOGGER.error("文件下载失败", e);
response.setCode(1);
response.setContent(null);
if (e instanceof FileNotFoundException) {
response.setMsg("文件不存在!!!");
}else {
} else {
response.setMsg(e.getMessage());
}
return response;
@@ -104,30 +125,35 @@ public class DownloadUtils {
* 对最有一个路径进行转码
* @param urlAddress
* http://192.168.2.111:8013/demo/Handle中文.zip
* http://192.168.2.111:8013/download?id=1&filename=中文.zip
* @return
*/
private String encodeUrlParam(String urlAddress) {
String newUrl = "";
try {
String path = "";
String param = "";
if (urlAddress.contains("?")) {
path = urlAddress.substring(0, urlAddress.indexOf("?"));
param = urlAddress.substring(urlAddress.indexOf("?"));
}else {
path = urlAddress;
private String encodeUrlParam(String urlAddress){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < urlAddress.length(); i++) {
char c = urlAddress.charAt(i);
if (c >= 0 && c <= 255) {
sb.append(c);
} else {
byte[] b;
try {
//指定需要的编码类型
b = String.valueOf(c).getBytes("utf-8");
} catch (Exception ex) {
System.out.println(ex);
b = new byte[0];
}
for (int j = 0; j < b.length; j++) {
int k = b[j];
if (k < 0) {
k += 256;
}
sb.append("%" + Integer.toHexString(k).toUpperCase());
}
}
String lastPath = path.substring(path.lastIndexOf("/") + 1);
String leftPath = path.substring(0, path.lastIndexOf("/") + 1);
String encodeLastPath = URLEncoder.encode(lastPath, "UTF-8");
newUrl += leftPath + encodeLastPath;
if (urlAddress.contains("?")) {
newUrl += param;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return newUrl;
return sb.toString();
}

View File

@@ -1,20 +1,20 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.FileType;
import cn.keking.service.cache.CacheService;
import com.google.common.collect.Lists;
import org.redisson.api.RMapCache;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -25,31 +25,22 @@ import java.util.Map;
*/
@Component
public class FileUtils {
public static final String DEFAULT_CONVERTER_CHARSET = System.getProperty("sun.jnu.encoding");
Logger log= LoggerFactory.getLogger(getClass());
final String REDIS_FILE_PREVIEW_PDF_KEY = "converted-preview-pdf-file";
final String REDIS_FILE_PREVIEW_IMGS_KEY = "converted-preview-imgs-file";//压缩包内图片文件集合
@Autowired
RedissonClient redissonClient;
@Value("${file.dir}")
String fileDir;
CacheService cacheService;
@Value("${converted.file.charset}")
String charset;
String fileDir = ConfigConstants.getFileDir();
@Value("${simText}")
String[] simText;
@Value("${media}")
String[] media;
/**
* 已转换过的文件集合(redis缓存)
* @return
*/
public Map<String, String> listConvertedFiles() {
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
return convertedList;
return cacheService.getPDFCache();
}
/**
@@ -57,8 +48,16 @@ public class FileUtils {
* @return
*/
public String getConvertedFile(String key) {
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
return convertedList.get(key);
return cacheService.getPDFCache(key);
}
/**
* 已将pdf转换成图片的图片本地路径
* @param key pdf本地路径
* @return
*/
public Integer getConvertedPdfImage(String key) {
return cacheService.getPdfImageCache(key);
}
/**
@@ -70,9 +69,15 @@ public class FileUtils {
public FileType typeFromUrl(String url) {
String nonPramStr = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?") : url.length());
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
return typeFromFileName(fileName);
}
private FileType typeFromFileName(String fileName) {
String[] simText = ConfigConstants.getSimText();
String[] media = ConfigConstants.getMedia();
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
if (listPictureTypes().contains(fileType.toLowerCase())) {
return FileType.picture;
return FileType.picture;
}
if (listArchiveTypes().contains(fileType.toLowerCase())) {
return FileType.compress;
@@ -170,8 +175,16 @@ public class FileUtils {
}
public void addConvertedFile(String fileName, String value){
RMapCache<String, String> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_PDF_KEY);
convertedList.fastPut(fileName, value);
cacheService.putPDFCache(fileName, value);
}
/**
*
* @param pdfFilePath
* @param num
*/
public void addConvertedPdfImage(String pdfFilePath, int num){
cacheService.putPdfImageCache(pdfFilePath, num);
}
/**
@@ -180,8 +193,7 @@ public class FileUtils {
* @return
*/
public List getRedisImgUrls(String fileKey){
RMapCache<String, List> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
return convertedList.get(fileKey);
return cacheService.getImgCache(fileKey);
}
/**
@@ -190,8 +202,7 @@ public class FileUtils {
* @param imgs
*/
public void setRedisImgUrls(String fileKey,List imgs){
RMapCache<String, List> convertedList = redissonClient.getMapCache(REDIS_FILE_PREVIEW_IMGS_KEY);
convertedList.fastPut(fileKey,imgs);
cacheService.putImgCache(fileKey, imgs);
}
/**
* 判断文件编码格式
@@ -226,7 +237,7 @@ public class FileUtils {
public void doActionConvertedFile(String outFilePath) {
StringBuffer sb = new StringBuffer();
try (InputStream inputStream = new FileInputStream(outFilePath);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, charset))){
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, DEFAULT_CONVERTER_CHARSET))){
String line;
while(null != (line = reader.readLine())){
if (line.contains("charset=gb2312")) {
@@ -237,7 +248,7 @@ public class FileUtils {
// 添加sheet控制头
sb.append("<script src=\"js/jquery-3.0.0.min.js\" type=\"text/javascript\"></script>");
sb.append("<script src=\"js/excel.header.js\" type=\"text/javascript\"></script>");
sb.append("<link rel=\"stylesheet\" href=\"http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css\">");
sb.append("<link rel=\"stylesheet\" href=\"//cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css\">");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
@@ -245,7 +256,7 @@ public class FileUtils {
}
// 重新写入文件
try(FileOutputStream fos = new FileOutputStream(outFilePath);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos))){
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"))) {
writer.write(sb.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
@@ -261,22 +272,76 @@ public class FileUtils {
private String suffixFromUrl(String url) {
String nonPramStr = url.substring(0, url.indexOf("?") != -1 ? url.indexOf("?") : url.length());
String fileName = nonPramStr.substring(nonPramStr.lastIndexOf("/") + 1);
return suffixFromFileName(fileName);
}
private String suffixFromFileName(String fileName) {
String fileType = fileName.substring(fileName.lastIndexOf(".") + 1);
return fileType;
}
public FileAttribute getFileAttribute(String url) {
String decodedUrl=null;
try {
decodedUrl = URLDecoder.decode(url, "utf-8");
}catch (UnsupportedEncodingException e){
log.debug("url解码失败");
/**
* 获取url中的参数
* @param url
* @param name
* @return
*/
public String getUrlParameterReg(String url, String name) {
Map<String, String> mapRequest = new HashMap();
String strUrlParam = truncateUrlPage(url);
if (strUrlParam == null) {
return "";
}
// 路径转码
FileType type = typeFromUrl(url);
String suffix = suffixFromUrl(url);
// 抽取文件并返回文件列表
String fileName = getFileNameFromURL(decodedUrl);
return new FileAttribute(type,suffix,fileName,url,decodedUrl);
//每个键值为一组
String[] arrSplit=strUrlParam.split("[&]");
for(String strSplit:arrSplit) {
String[] arrSplitEqual= strSplit.split("[=]");
//解析出键值
if(arrSplitEqual.length > 1) {
//正确解析
mapRequest.put(arrSplitEqual[0], arrSplitEqual[1]);
} else if (!arrSplitEqual[0].equals("")) {
//只有参数没有值,不加入
mapRequest.put(arrSplitEqual[0], "");
}
}
return mapRequest.get(name);
}
/**
* 去掉url中的路径留下请求参数部分
* @param strURL url地址
* @return url请求参数部分
*/
private String truncateUrlPage(String strURL) {
String strAllParam = null;
strURL = strURL.trim();
String[] arrSplit = strURL.split("[?]");
if(strURL.length() > 1) {
if(arrSplit.length > 1) {
if(arrSplit[1] != null) {
strAllParam=arrSplit[1];
}
}
}
return strAllParam;
}
public FileAttribute getFileAttribute(String url) {
String fileName;
FileType type;
String suffix;
String fullFileName = getUrlParameterReg(url, "fullfilename");
if (!StringUtils.isEmpty(fullFileName)) {
fileName = fullFileName;
type = typeFromFileName(fileName);
suffix = suffixFromFileName(fileName);
} else {
fileName = getFileNameFromURL(url);
type = typeFromUrl(url);
suffix = suffixFromUrl(url);
}
return new FileAttribute(type,suffix,fileName,url,url);
}
}

View File

@@ -0,0 +1,57 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
/**
* @auther: chenjh
* @since: 2019/6/18 14:36
*/
public class FtpUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(FtpUtils.class);
public static FTPClient connect(String host, int port, String username, String password, String controlEncoding) throws IOException {
FTPClient ftpClient = new FTPClient();
ftpClient.connect(host, port);
if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
ftpClient.login(username, password);
}
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
}
ftpClient.setControlEncoding(controlEncoding);
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
return ftpClient;
}
public static void download(String ftpUrl, String localFilePath, String ftpUsername, String ftpPassword, String ftpControlEncoding) throws IOException {
String username = StringUtils.isEmpty(ftpUsername) ? ConfigConstants.getFtpUsername() : ftpUsername;
String password = StringUtils.isEmpty(ftpPassword) ? ConfigConstants.getFtpPassword() : ftpPassword;
String controlEncoding = StringUtils.isEmpty(ftpControlEncoding) ? ConfigConstants.getFtpControlEncoding() : ftpControlEncoding;
URL url = new URL(ftpUrl);
String host = url.getHost();
int port = (url.getPort() == -1) ? url.getDefaultPort() : url.getPort();
String remoteFilePath = url.getPath();
LOGGER.debug("FTP connection url:{}, username:{}, password:{}, controlEncoding:{}, localFilePath:{}", ftpUrl, username, password, controlEncoding, localFilePath);
FTPClient ftpClient = connect(host, port, username, password, controlEncoding);
OutputStream outputStream = new FileOutputStream(localFilePath);
ftpClient.enterLocalPassiveMode();
boolean downloadResult = ftpClient.retrieveFile(new String(remoteFilePath.getBytes(controlEncoding), "ISO-8859-1"), outputStream);
LOGGER.debug("FTP download result {}", downloadResult);
outputStream.flush();
outputStream.close();
ftpClient.logout();
ftpClient.disconnect();
}
}

View File

@@ -0,0 +1,66 @@
package cn.keking.utils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.tools.imageio.ImageIOUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Component
public class PdfUtils {
private final Logger LOGGER = LoggerFactory.getLogger(PdfUtils.class);
@Autowired
FileUtils fileUtils;
public List<String> pdf2jpg(String pdfFilePath, String pdfName, String url) {
List<String> imageUrls = new ArrayList<>();
Integer imageCount = fileUtils.getConvertedPdfImage(pdfFilePath);
String imageFileSuffix = ".jpg";
// https://8个字符 http://7个字符 从这后面开始出现的第一个/就是当前file.Dir下的根目录
int index1 = url.indexOf("/", 8);
String pdfFolder = pdfName.substring(0, pdfName.length() - 4);
String urlPrefix = url.substring(0, index1 + 1) + pdfFolder;
if (imageCount != null && imageCount.intValue() > 0) {
for (int i = 0; i < imageCount ; i++)
imageUrls.add(urlPrefix + "/" + i + imageFileSuffix);
return imageUrls;
}
try {
File pdfFile = new File(pdfFilePath);
PDDocument doc = PDDocument.load(pdfFile);
int pageCount = doc.getNumberOfPages();
PDFRenderer pdfRenderer = new PDFRenderer(doc);
int index = pdfFilePath.lastIndexOf(".");
String folder = pdfFilePath.substring(0, index);
File path = new File(folder);
if (!path.exists()) {
path.mkdirs();
}
String imageFilePath;
for (int pageIndex = 0; pageIndex < pageCount; pageIndex++) {
imageFilePath = folder + File.separator + pageIndex + imageFileSuffix;
BufferedImage image = pdfRenderer.renderImageWithDPI(pageIndex, 105, ImageType.RGB);
ImageIOUtil.writeImage(image, imageFilePath, 105);
imageUrls.add(urlPrefix + "/" + pageIndex + imageFileSuffix);
}
doc.close();
fileUtils.addConvertedPdfImage(pdfFilePath, pageCount);
} catch (IOException e) {
LOGGER.error("Convert pdf to jpg exception", e);
}
return imageUrls;
}
}

View File

@@ -1,16 +1,35 @@
package cn.keking.utils;
import org.springframework.beans.factory.annotation.Value;
import cn.keking.config.ConfigConstants;
import cn.keking.service.cache.CacheService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* @auther: chenjh
* @since: 2019/6/11 7:45
*/
@Component
@ConditionalOnExpression("'${cache.clean.enabled:false}'.equals('true')")
public class ShedulerClean {
@Value("${file.dir}")
String fileDir;
// @Scheduled(cron = "0 0 23 * * ?") //每晚23点执行一次
public void clean(){
System.out.println("执行一次清空文件夹");
private static final Logger LOGGER = LoggerFactory.getLogger(ShedulerClean.class);
@Autowired
private CacheService cacheService;
private String fileDir = ConfigConstants.getFileDir();
//默认每晚3点执行一次
@Scheduled(cron = "${cache.clean.cron:0 0 3 * * ?}")
public void clean() {
LOGGER.info("Cache clean start");
cacheService.cleanCache();
DeleteFileUtil.deleteDirectory(fileDir);
LOGGER.info("Cache clean end");
}
}

View File

@@ -1,8 +1,9 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.model.ReturnResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
@@ -12,13 +13,14 @@ import org.springframework.stereotype.Component;
*/
@Component
public class SimTextUtil {
@Value("${file.dir}")
String fileDir;
@Autowired
DownloadUtils downloadUtils;
private FileUtils fileUtils;
@Autowired
private DownloadUtils downloadUtils;
public ReturnResponse<String> readSimText(String url, String fileName){
ReturnResponse<String> response = downloadUtils.downLoad(url, "txt", fileName);
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
ReturnResponse<String> response = downloadUtils.downLoad(fileAttribute, fileName);
return response;
}
}

View File

@@ -1,5 +1,6 @@
package cn.keking.utils;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileType;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -8,10 +9,11 @@ import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
@@ -36,8 +38,7 @@ public class ZipReader {
@Autowired
FileUtils fileUtils;
@Value("${file.dir}")
String fileDir;
String fileDir = ConfigConstants.getFileDir();
ExecutorService executors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
@@ -121,7 +122,7 @@ public class ZipReader {
List imgUrls=Lists.newArrayList();
String baseUrl= (String) RequestContextHolder.currentRequestAttributes().getAttribute("baseUrl",0);
try {
Archive archive = new Archive(new File(filePath));
Archive archive = new Archive(new FileInputStream(new File(filePath)));
List<FileHeader> headers = archive.getFileHeaders();
headers = sortedHeaders(headers);
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
@@ -161,6 +162,71 @@ public class ZipReader {
return null;
}
/**
* 解压7z文件
* @param filePath
* @param fileKey
* @return
*/
public String read7zFile(String filePath,String fileKey) {
String archiveSeparator = "/";
Map<String, FileNode> appender = Maps.newHashMap();
List imgUrls=Lists.newArrayList();
String baseUrl= (String) RequestContextHolder.currentRequestAttributes().getAttribute("baseUrl",0);
String archiveFileName = fileUtils.getFileNameFromPath(filePath);
try {
SevenZFile zipFile = new SevenZFile(new File(filePath));
Iterable<SevenZArchiveEntry> entries = zipFile.getEntries();
// 排序
Enumeration<SevenZArchiveEntry> newEntries = sortSevenZEntries(entries);
List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted = Lists.newArrayList();
while (newEntries.hasMoreElements()){
SevenZArchiveEntry entry = newEntries.nextElement();
String fullName = entry.getName();
int level = fullName.split(archiveSeparator).length;
// 展示名
String originName = getLastFileName(fullName, archiveSeparator);
String childName = level + "_" + originName;
boolean directory = entry.isDirectory();
if (!directory) {
childName = archiveFileName + "_" + originName;
entriesToBeExtracted.add(Collections.singletonMap(childName, entry));
}
String parentName = getLast2FileName(fullName, archiveSeparator, archiveFileName);
parentName = (level-1) + "_" + parentName;
FileType type=fileUtils.typeFromUrl(childName);
if (type.equals(FileType.picture)){//添加图片文件到图片列表
imgUrls.add(baseUrl+childName);
}
FileNode node = new FileNode(originName, childName, parentName, new ArrayList<>(), directory,fileKey);
addNodes(appender, parentName, node);
appender.put(childName, node);
}
// 开启新的线程处理文件解压
executors.submit(new SevenZExtractorWorker(entriesToBeExtracted, filePath));
fileUtils.setRedisImgUrls(fileKey,imgUrls);
return new ObjectMapper().writeValueAsString(appender.get(""));
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 排序7ZEntries(对原来列表倒序)
* @param entries
*/
private Enumeration<SevenZArchiveEntry> sortSevenZEntries(Iterable<SevenZArchiveEntry> entries) {
List<SevenZArchiveEntry> sortedEntries = Lists.newArrayList();
Iterator<SevenZArchiveEntry> iterator = entries.iterator();
while(iterator.hasNext()){
sortedEntries.add(iterator.next());
}
// Collections.sort(sortedEntries, Comparator.comparingInt(o -> o.getName().length()));
return Collections.enumeration(sortedEntries);
}
private void addNodes(Map<String, FileNode> appender, String parentName, FileNode node) {
if (appender.containsKey(parentName)) {
appender.get(parentName).getChildList().add(node);
@@ -177,10 +243,10 @@ public class ZipReader {
private List<FileHeader> sortedHeaders(List<FileHeader> headers) {
List<FileHeader> sortedHeaders = new ArrayList<>();
Map<Integer, FileHeader> mapHeaders = new TreeMap<>();
headers.forEach(header -> mapHeaders.put(header.getFileNameW().length(), header));
headers.forEach(header -> mapHeaders.put(new Integer(0).equals(header.getFileNameW().length()) ? header.getFileNameString().length() : header.getFileNameW().length(), header));
for (Map.Entry<Integer, FileHeader> entry : mapHeaders.entrySet()){
for (FileHeader header : headers) {
if (entry.getKey().intValue() == header.getFileNameW().length()) {
if (entry.getKey().equals(new Integer(0).equals(header.getFileNameW().length()) ? header.getFileNameString().length() : header.getFileNameW().length())) {
sortedHeaders.add(header);
}
}
@@ -403,6 +469,60 @@ public class ZipReader {
}
}
/**
* 7z文件抽取线程
*/
class SevenZExtractorWorker implements Runnable {
private List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted;
private String filePath;
public SevenZExtractorWorker(List<Map<String, SevenZArchiveEntry>> entriesToBeExtracted, String filePath) {
this.entriesToBeExtracted = entriesToBeExtracted;
this.filePath = filePath;
}
@Override
public void run() {
System.out.println("解析压缩文件开始《《《《《《《《《《《《《《《《《《《《《《《");
try {
SevenZFile sevenZFile = new SevenZFile(new File(filePath));
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
while (entry != null) {
if (entry.isDirectory()) {
entry = sevenZFile.getNextEntry();
continue;
}
String childName = "default_file";
SevenZArchiveEntry entry1 = null;
for (Map<String, SevenZArchiveEntry> entryMap : entriesToBeExtracted) {
childName = entryMap.keySet().iterator().next();
entry1 = entryMap.values().iterator().next();
if (entry.getName().equals(entry1.getName())) {
break;
}
}
FileOutputStream out = new FileOutputStream(fileDir + childName);
byte[] content = new byte[(int) entry.getSize()];
sevenZFile.read(content, 0, content.length);
out.write(content);
out.close();
entry = sevenZFile.getNextEntry();
}
sevenZFile.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (new File(filePath).exists()) {
new File(filePath).delete();
}
System.out.println("解析压缩文件结束《《《《《《《《《《《《《《《《《《《《《《《");
}
}
/**
* Rar文件抽取
*/

View File

@@ -1,5 +1,6 @@
package cn.keking.web.controller;
import cn.keking.config.ConfigConstants;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
@@ -7,7 +8,6 @@ import com.google.common.collect.Lists;
import cn.keking.model.ReturnResponse;
import cn.keking.utils.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@@ -28,8 +28,7 @@ import java.util.UUID;
*/
@RestController
public class FileController {
@Value("${file.dir}")
String fileDir;
String fileDir = ConfigConstants.getFileDir();
@Autowired
FileUtils fileUtils;
String demoDir = "demo";
@@ -38,7 +37,19 @@ public class FileController {
@RequestMapping(value = "fileUpload", method = RequestMethod.POST)
public String fileUpload(@RequestParam("file") MultipartFile file,
HttpServletRequest request) throws JsonProcessingException {
// 获取文件名
String fileName = file.getOriginalFilename();
//判断是否为IE浏览器的文件名IE浏览器下文件名会带有盘符信息
// Check for Unix-style path
int unixSep = fileName.lastIndexOf('/');
// Check for Windows-style path
int winSep = fileName.lastIndexOf('\\');
// Cut off at latest possible point
int pos = (winSep > unixSep ? winSep : unixSep);
if (pos != -1) {
fileName = fileName.substring(pos + 1);
}
// 判断该文件类型是否有上传过,如果上传过则提示不允许再次上传
if (existsTypeFile(fileName)) {
return new ObjectMapper().writeValueAsString(new ReturnResponse<String>(1, "每一种类型只可以上传一个文件,请先删除原有文件再次上传", null));

View File

@@ -1,12 +1,15 @@
package cn.keking.web.controller;
import cn.keking.service.FileConverQueueTask;
import cn.keking.config.ConfigConstants;
import cn.keking.model.FileAttribute;
import cn.keking.service.FilePreview;
import cn.keking.service.FilePreviewFactory;
import cn.keking.service.cache.CacheService;
import cn.keking.utils.FileUtils;
import org.apache.commons.io.IOUtils;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@@ -17,16 +20,10 @@ import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.io.*;
import java.net.*;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @author yudian-it
@@ -34,11 +31,18 @@ import java.util.Map;
@Controller
public class OnlinePreviewController {
private static final Logger LOGGER = LoggerFactory.getLogger(OnlinePreviewController.class);
@Autowired
FilePreviewFactory previewFactory;
@Autowired
RedissonClient redissonClient;
CacheService cacheService;
@Autowired
private FileUtils fileUtils;
private String fileDir = ConfigConstants.getFileDir();
/**
* @param url
@@ -47,9 +51,12 @@ public class OnlinePreviewController {
*/
@RequestMapping(value = "onlinePreview", method = RequestMethod.GET)
public String onlinePreview(String url, Model model, HttpServletRequest req) {
FileAttribute fileAttribute = fileUtils.getFileAttribute(url);
req.setAttribute("fileKey", req.getParameter("fileKey"));
FilePreview filePreview = previewFactory.get(url);
return filePreview.filePreviewHandle(url, model);
model.addAttribute("officePreviewType", req.getParameter("officePreviewType"));
model.addAttribute("originUrl", req.getRequestURL().toString());
FilePreview filePreview = previewFactory.get(fileAttribute);
return filePreview.filePreviewHandle(url, model, fileAttribute);
}
/**
@@ -99,7 +106,7 @@ public class OnlinePreviewController {
InputStream inputStream = null;
try {
String strUrl = urlPath.trim();
URL url = new URL(strUrl);
URL url = new URL(new URI(strUrl).toASCIIString());
//打开请求连接
URLConnection connection = url.openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
@@ -110,8 +117,8 @@ public class OnlinePreviewController {
while (-1 != (len = inputStream.read(bs))) {
resp.getOutputStream().write(bs, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} catch (IOException | URISyntaxException e) {
LOGGER.error("下载pdf文件失败", e);
} finally {
if (inputStream != null) {
IOUtils.closeQuietly(inputStream);
@@ -126,8 +133,7 @@ public class OnlinePreviewController {
@GetMapping("/addTask")
@ResponseBody
public String addQueueTask(String url) {
final RBlockingQueue<String> queue = redissonClient.getBlockingQueue(FileConverQueueTask.queueTaskName);
queue.addAsync(url);
cacheService.addQueueTask(url);
return "success";
}

View File

View File

@@ -0,0 +1,54 @@
<!--***********************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
***********************************************************-->
<xsl:stylesheet version="1.0" encoding="UTF-8"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:office="http://openoffice.org/2000/office"
xmlns:style="http://openoffice.org/2000/style"
xmlns:table="http://openoffice.org/2000/table"
xmlns:draw="http://openoffice.org/2000/drawing"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:meta="http://openoffice.org/2000/meta"
xmlns:number="http://openoffice.org/2000/datastyle"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:chart="http://openoffice.org/2000/chart"
xmlns:help="http://openoffice.org/2000/help"
xmlns:index="http://sun.com/2000/XMLSearch"
xmlns:text="http://openoffice.org/2000/text">
<xsl:param name="Language" select="'en-US'"/>
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/">
<xsl:apply-templates select="//title" mode="include"/>
<xsl:apply-templates select="//paragraph[@role='heading']" mode="include"/>
</xsl:template>
<xsl:template match="*" mode="include">
<xsl:value-of select="."/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="*"/>
</xsl:stylesheet>

View File

@@ -0,0 +1,124 @@
<!--***********************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
***********************************************************-->
<xsl:stylesheet version="1.0" encoding="UTF-8"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:office="http://openoffice.org/2000/office"
xmlns:style="http://openoffice.org/2000/style"
xmlns:table="http://openoffice.org/2000/table"
xmlns:draw="http://openoffice.org/2000/drawing"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:meta="http://openoffice.org/2000/meta"
xmlns:number="http://openoffice.org/2000/datastyle"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:chart="http://openoffice.org/2000/chart"
xmlns:help="http://openoffice.org/2000/help"
xmlns:index="http://sun.com/2000/XMLSearch"
xmlns:text="http://openoffice.org/2000/text">
<xsl:param name="Language" select="'en-US'"/>
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="helpdocument|body">
<xsl:choose>
<xsl:when test="meta/topic[@indexer='exclude']"/>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="title">
<xsl:value-of select="."/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="table">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="tablecell">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="tablerow">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="list">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="listitem">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="item">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="emph">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="paragraph">
<xsl:value-of select="."/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="section">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="bookmark">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="bookmark_value">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="link">
<xsl:apply-templates/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="ahelp[@visibility='visible']">
<xsl:value-of select="."/>
<xsl:text>&#xA;</xsl:text>
</xsl:template>
<xsl:template match="*"/>
</xsl:stylesheet>

View File

@@ -0,0 +1,960 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--***********************************************************************
This is the main transformation style sheet for transforming.
Only use with OOo 2.0
Owner: fpe@openoffice.org
=========================================================================
Changes Log
May 24 2004 Created
Aug 24 2004 Fixed for help2 CWS
Aug 27 2004 Added css link, fixed missing embed-mode for variable
Removed width/height for images
Sep 03 2004 Modularized xsl, added some embedded modes
Oct 08 2004 Fixed bug wrong mode "embedded" for links
Added embedded modes for embed and embedvar (for cascaded embeds)
Added <p> tags around falsely embedded pars and vars
Dec 08 2004 #i38483#, fixed wrong handling of web links
#i37377#, fixed missing usage of Database parameter for switching
Jan 04 2005 #i38905#, fixed buggy branding replacement template
Mar 17 2005 #i43972#, added language info to image URL, evaluate Language parameter
evaluate new localize attribute in images
May 10 2005 #i48785#, fixed wrong setting of distrib variable
Aug 16 2005 workaround for #i53365#
Aug 19 2005 fixed missing list processing in embedded sections
Aug 19 2005 #i53535#, fixed wrong handling of Database parameter
Oct 17 2006 #i70462#, disabled sorting to avoid output of error messages to console
Jun 15 2009 #i101799#, fixed wrong handling of http URLs with anchors
***********************************************************************//-->
<!--***********************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
***********************************************************-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="html"/>
<!--
############################
# Variables and Parameters #
############################
//-->
<!-- General Usage -->
<xsl:variable name="am" select="'&amp;'"/>
<xsl:variable name="sl" select="'/'"/>
<xsl:variable name="qt" select="'&quot;'"/>
<!-- generic Icon alt text -->
<xsl:variable name="alttext" select="'text/shared/00/icon_alt.xhp'"/>
<!-- For calculating pixel sizes -->
<xsl:variable name="dpi" select="'96'"/>
<xsl:variable name="dpcm" select="'38'"/>
<!-- Product brand variables used in the help files -->
<xsl:variable name="brand1" select="'$[officename]'"/>
<xsl:variable name="brand2" select="'$[officeversion]'"/>
<xsl:variable name="brand3" select="'%PRODUCTNAME'"/>
<xsl:variable name="brand4" select="'%PRODUCTVERSION'"/>
<!-- meta data variables from the help file -->
<xsl:variable name="filename" select="/helpdocument/meta/topic/filename"/>
<xsl:variable name="topic_id" select="/helpdocument/meta/topic/@id"/>
<xsl:variable name="topic_status" select="/helpdocument/meta/topic/@status"/>
<xsl:variable name="title" select="/helpdocument/meta/topic/title"/>
<xsl:variable name="doclang" select="/helpdocument/meta/topic/title/@xml-lang"/>
<!-- Module and the corresponding switching values-->
<xsl:param name="Database" select="'swriter'"/>
<xsl:variable name="module" select="$Database"/>
<xsl:variable name="appl">
<xsl:choose>
<xsl:when test="$module = 'swriter'"><xsl:value-of select="'WRITER'"/></xsl:when>
<xsl:when test="$module = 'scalc'"><xsl:value-of select="'CALC'"/></xsl:when>
<xsl:when test="$module = 'sdraw'"><xsl:value-of select="'DRAW'"/></xsl:when>
<xsl:when test="$module = 'simpress'"><xsl:value-of select="'IMPRESS'"/></xsl:when>
<xsl:when test="$module = 'schart'"><xsl:value-of select="'CHART'"/></xsl:when>
<xsl:when test="$module = 'sbasic'"><xsl:value-of select="'BASIC'"/></xsl:when>
<xsl:when test="$module = 'smath'"><xsl:value-of select="'MATH'"/></xsl:when>
</xsl:choose>
</xsl:variable>
<!-- the other parameters given by the help caller -->
<xsl:param name="System" select="'WIN'"/>
<xsl:param name="productname" select="'Office'"/>
<xsl:param name="productversion" select="''"/>
<xsl:variable name="pversion">
<xsl:value-of select="translate($productversion,' ','')"/>
</xsl:variable>
<!-- this is were the images are -->
<xsl:param name="imgrepos" select="''"/>
<xsl:param name="Id" />
<!-- (lame) distinction between OS and Commercial -->
<xsl:param name="distrib">
<xsl:choose>
<xsl:when test="starts-with($productname,'OpenOffice')">
<xsl:value-of select="'OpenSource'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'COMMERCIAL'"/>
</xsl:otherwise>
</xsl:choose>
</xsl:param>
<xsl:param name="Language" select="'en-US'"/>
<xsl:variable name="lang" select="$Language"/>
<xsl:param name="ExtensionId" select="''"/>
<xsl:param name="ExtensionPath" select="''"/>
<!-- parts of help and image urls -->
<xsl:variable name="help_url_prefix" select="'vnd.sun.star.help://'"/>
<xsl:variable name="img_url_prefix" select="concat('vnd.sun.star.zip://',$imgrepos,'/')"/>
<xsl:variable name="urlpost" select="concat('?Language=',$lang,$am,'System=',$System,$am,'UseDB=no')"/>
<xsl:variable name="urlpre" select="$help_url_prefix" />
<xsl:variable name="linkprefix" select="$urlpre"/>
<xsl:variable name="linkpostfix" select="$urlpost"/>
<xsl:variable name="css" select="'default.css'"/>
<!-- images for notes, tips and warnings -->
<xsl:variable name="note_img" select="concat($img_url_prefix,'res/helpimg/note.png')"/>
<xsl:variable name="tip_img" select="concat($img_url_prefix,'res/helpimg/tip.png')"/>
<xsl:variable name="warning_img" select="concat($img_url_prefix,'res/helpimg/warning.png')"/>
<!--
#############
# Templates #
#############
//-->
<!-- Create the document skeleton -->
<xsl:template match="/">
<xsl:variable name="csslink" select="concat($urlpre,'/',$urlpost)"/>
<html>
<head>
<title><xsl:value-of select="$title"/></title>
<link href="{$csslink}" rel="Stylesheet" type="text/css" /> <!-- stylesheet link -->
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
</head>
<body lang="{$lang}">
<xsl:apply-templates select="/helpdocument/body"/>
</body>
</html>
</xsl:template>
<!-- AHELP -->
<xsl:template match="ahelp">
<xsl:if test="not(@visibility='hidden')"><span class="avis"><xsl:apply-templates /></span></xsl:if>
</xsl:template>
<!-- ALT -->
<xsl:template match="alt"/>
<!-- BOOKMARK -->
<xsl:template match="bookmark">
<a name="{@id}"></a>
<xsl:choose>
<xsl:when test="starts-with(@branch,'hid')" />
<xsl:otherwise><xsl:apply-templates /></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="bookmark" mode="embedded" />
<!-- BOOKMARK_VALUE -->
<xsl:template match="bookmark_value" />
<!-- BR -->
<xsl:template match="br"><br /></xsl:template>
<!-- CAPTION -->
<xsl:template match="caption" />
<!-- CASE -->
<xsl:template match="case"><xsl:call-template name="insertcase" /></xsl:template>
<xsl:template match="case" mode="embedded">
<xsl:call-template name="insertcase">
<xsl:with-param name="embedded" select="'yes'"/>
</xsl:call-template>
</xsl:template>
<!-- CASEINLINE -->
<xsl:template match="caseinline"><xsl:call-template name="insertcase" /></xsl:template>
<xsl:template match="caseinline" mode="embedded">
<xsl:call-template name="insertcase">
<xsl:with-param name="embedded" select="'yes'"/>
</xsl:call-template>
</xsl:template>
<!-- COMMENT -->
<xsl:template match="comment" />
<xsl:template match="comment" mode="embedded"/>
<!-- CREATED -->
<xsl:template match="created" />
<!-- DEFAULT -->
<xsl:template match="default"><xsl:call-template name="insertdefault" /></xsl:template>
<xsl:template match="default" mode="embedded">
<xsl:call-template name="insertdefault">
<xsl:with-param name="embedded" select="'yes'"/>
</xsl:call-template>
</xsl:template>
<!-- DEFAULTINLINE -->
<xsl:template match="defaultinline"><xsl:call-template name="insertdefault" /></xsl:template>
<xsl:template match="defaultinline" mode="embedded">
<xsl:call-template name="insertdefault">
<xsl:with-param name="embedded" select="'yes'"/>
</xsl:call-template>
</xsl:template>
<!-- EMBED -->
<xsl:template match="embed"><xsl:call-template name="resolveembed"/></xsl:template>
<xsl:template match="embed" mode="embedded"><xsl:call-template name="resolveembed"/></xsl:template>
<!-- EMBEDVAR -->
<xsl:template match="embedvar"><xsl:call-template name="resolveembedvar"/></xsl:template>
<xsl:template match="embedvar" mode="embedded"><xsl:call-template name="resolveembedvar"/></xsl:template>
<!-- EMPH -->
<xsl:template match="emph">
<span class="emph"><xsl:apply-templates /></span>
</xsl:template>
<xsl:template match="emph" mode="embedded">
<span class="emph"><xsl:apply-templates /></span>
</xsl:template>
<!-- FILENAME -->
<xsl:template match="filename" />
<!-- HISTORY -->
<xsl:template match="history" />
<!-- IMAGE -->
<xsl:template match="image"><xsl:call-template name="insertimage"/></xsl:template>
<xsl:template match="image" mode="embedded"><xsl:call-template name="insertimage"/></xsl:template>
<!-- ITEM -->
<xsl:template match="item"><span class="{@type}"><xsl:apply-templates /></span></xsl:template>
<xsl:template match="item" mode="embedded"><span class="{@type}"><xsl:apply-templates /></span></xsl:template>
<!-- LASTEDITED -->
<xsl:template match="lastedited" />
<!-- LINK -->
<xsl:template match="link">
<xsl:choose> <!-- don't insert the heading link to itself -->
<xsl:when test="(concat('/',@href) = /helpdocument/meta/topic/filename) or (@href = /helpdocument/meta/topic/filename)">
<xsl:apply-templates />
</xsl:when>
<xsl:when test="contains(child::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
<xsl:call-template name="insert_howtoget">
<xsl:with-param name="linkhref" select="@href"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="createlink" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="link" mode="embedded">
<xsl:call-template name="createlink"/>
</xsl:template>
<!-- LIST -->
<xsl:template match="list">
<xsl:choose>
<xsl:when test="@type='ordered'">
<ol>
<xsl:if test="@startwith">
<xsl:attribute name="start"><xsl:value-of select="@startwith"/></xsl:attribute>
</xsl:if>
<xsl:apply-templates />
</ol>
</xsl:when>
<xsl:otherwise>
<ul><xsl:apply-templates /></ul>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="list" mode="embedded">
<xsl:choose>
<xsl:when test="@type='ordered'">
<ol>
<xsl:if test="@startwith">
<xsl:attribute name="start"><xsl:value-of select="@startwith"/></xsl:attribute>
</xsl:if>
<xsl:apply-templates mode="embedded"/>
</ol>
</xsl:when>
<xsl:otherwise>
<ul><xsl:apply-templates mode="embedded"/></ul>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- LISTITEM -->
<xsl:template match="listitem">
<li><xsl:apply-templates /></li>
</xsl:template>
<xsl:template match="listitem" mode="embedded">
<li><xsl:apply-templates mode="embedded"/></li>
</xsl:template>
<!-- META, SEE HEADER -->
<xsl:template match="meta" />
<!-- OBJECT (UNUSED) -->
<xsl:template match="object" />
<!-- PARAGRAPH -->
<xsl:template match="paragraph">
<xsl:choose>
<xsl:when test="@role='heading'">
<xsl:call-template name="insertheading">
<xsl:with-param name="level" select="@level"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains(' note warning tip ',@role)">
<xsl:call-template name="insertnote">
<xsl:with-param name="type" select="@role" />
</xsl:call-template>
</xsl:when>
<xsl:when test="contains(descendant::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
<xsl:apply-templates />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="insertpara" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="paragraph" mode="embedded">
<xsl:choose>
<xsl:when test="@role='heading'"> <!-- increase the level of headings that are embedded -->
<!--
The internal sablotron processor does not seem to support the number function.
Therefore, we need a workaround for
<xsl:variable name="level"><xsl:value-of select="number(@level)+1"/></xsl:variable>
-->
<xsl:variable name="newlevel">
<xsl:choose>
<xsl:when test="@level='1'"><xsl:value-of select="'2'"/></xsl:when>
<xsl:when test="@level='2'"><xsl:value-of select="'2'"/></xsl:when>
<xsl:when test="@level='3'"><xsl:value-of select="'3'"/></xsl:when>
<xsl:when test="@level='4'"><xsl:value-of select="'4'"/></xsl:when>
<xsl:when test="@level='5'"><xsl:value-of select="'5'"/></xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:call-template name="insertheading">
<xsl:with-param name="level" select="$newlevel"/>
<xsl:with-param name="embedded" select="'yes'"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains(' note warning tip ',@role)">
<xsl:call-template name="insertnote">
<xsl:with-param name="type" select="@role" />
</xsl:call-template>
</xsl:when>
<xsl:when test="contains(descendant::embedvar/@href,'/00/00000004.xhp#wie')"> <!-- special treatment of howtoget links -->
<xsl:apply-templates />
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="insertpara" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- SECTION -->
<xsl:template match="section">
<a name="{@id}"></a>
<xsl:choose>
<xsl:when test="@id='relatedtopics'">
<div class="relatedtopics">
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,'shared/text/shared/00/00000004.xhp',$urlpost)"/></xsl:variable>
<xsl:variable name="anchor"><xsl:value-of select="'related'"/></xsl:variable>
<xsl:variable name="doc" select="document($href)"/>
<p class="related">
<xsl:apply-templates select="$doc//variable[@id=$anchor]"/>
</p>
<div class="relatedbody">
<xsl:apply-templates />
</div>
</div>
</xsl:when>
<xsl:when test="@id='howtoget'">
<xsl:call-template name="insert_howtoget" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- SECTION -->
<xsl:template match="section" mode="embedded">
<a name="{@id}"></a>
<xsl:apply-templates mode="embedded"/>
</xsl:template>
<!-- SORT -->
<xsl:template match="sort" >
<xsl:apply-templates><xsl:sort select="descendant::paragraph"/></xsl:apply-templates>
</xsl:template>
<xsl:template match="sort" mode="embedded">
<xsl:apply-templates><xsl:sort select="descendant::paragraph"/></xsl:apply-templates>
</xsl:template>
<!-- SWITCH -->
<xsl:template match="switch"><xsl:apply-templates /></xsl:template>
<xsl:template match="switch" mode="embedded"><xsl:apply-templates /></xsl:template>
<!-- SWITCHINLINE -->
<xsl:template match="switchinline"><xsl:apply-templates /></xsl:template>
<xsl:template match="switchinline" mode="embedded"><xsl:apply-templates mode="embedded"/></xsl:template>
<!-- TABLE -->
<xsl:template match="table"><xsl:call-template name="inserttable"/></xsl:template>
<xsl:template match="table" mode="embedded"><xsl:call-template name="inserttable"/></xsl:template>
<!-- TABLECELL -->
<xsl:template match="tablecell"><td valign="top"><xsl:apply-templates /></td></xsl:template>
<xsl:template match="tablecell" mode="icontable"><td valign="top"><xsl:apply-templates/></td></xsl:template>
<xsl:template match="tablecell" mode="embedded"><td valign="top"><xsl:apply-templates mode="embedded"/></td></xsl:template>
<!-- TABLEROW -->
<xsl:template match="tablerow"><tr><xsl:apply-templates /></tr></xsl:template>
<xsl:template match="tablerow" mode="icontable"><tr><xsl:apply-templates mode="icontable"/></tr></xsl:template>
<xsl:template match="tablerow" mode="embedded"><tr><xsl:apply-templates mode="embedded"/></tr></xsl:template>
<!-- TITLE -->
<xsl:template match="title"/>
<!-- TOPIC -->
<xsl:template match="topic"/>
<!-- VARIABLE -->
<xsl:template match="variable"><a name="{@id}"></a><xsl:apply-templates /></xsl:template>
<xsl:template match="variable" mode="embedded"><a name="{@id}"></a><xsl:apply-templates mode="embedded"/></xsl:template>
<xsl:template match="text()">
<xsl:call-template name="brand">
<xsl:with-param name="string"><xsl:value-of select="."/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template match="text()" mode="embedded">
<xsl:call-template name="brand">
<xsl:with-param name="string"><xsl:value-of select="."/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<!-- In case of missing help files -->
<xsl:template match="help-id-missing"><xsl:value-of select="$Id"/></xsl:template>
<!--
###################
# NAMED TEMPLATES #
###################
//-->
<!-- Branding -->
<xsl:template name="brand" >
<xsl:param name="string"/>
<xsl:choose>
<xsl:when test="contains($string,$brand1)">
<xsl:variable name="newstr">
<xsl:value-of select="substring-before($string,$brand1)"/>
<xsl:value-of select="$productname"/>
<xsl:value-of select="substring-after($string,$brand1)"/>
</xsl:variable>
<xsl:call-template name="brand">
<xsl:with-param name="string" select="$newstr"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string,$brand2)">
<xsl:variable name="newstr">
<xsl:value-of select="substring-before($string,$brand2)"/>
<xsl:value-of select="$pversion"/>
<xsl:value-of select="substring-after($string,$brand2)"/>
</xsl:variable>
<xsl:call-template name="brand">
<xsl:with-param name="string" select="$newstr"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string,$brand3)">
<xsl:variable name="newstr">
<xsl:value-of select="substring-before($string,$brand3)"/>
<xsl:value-of select="$productname"/>
<xsl:value-of select="substring-after($string,$brand3)"/>
</xsl:variable>
<xsl:call-template name="brand">
<xsl:with-param name="string" select="$newstr"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($string,$brand4)">
<xsl:variable name="newstr">
<xsl:value-of select="substring-before($string,$brand4)"/>
<xsl:value-of select="$pversion"/>
<xsl:value-of select="substring-after($string,$brand4)"/>
</xsl:variable>
<xsl:call-template name="brand">
<xsl:with-param name="string" select="$newstr"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Insert Paragraph -->
<xsl:template name="insertpara">
<xsl:variable name="role">
<xsl:choose>
<xsl:when test="ancestor::table">
<xsl:value-of select="concat(@role,'intable')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@role"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<p class="{$role}"><xsl:apply-templates /></p>
</xsl:template>
<!-- Insert "How to get Link" -->
<xsl:template name="insert_howtoget">
<xsl:param name="linkhref" />
<xsl:variable name="archive" select="'shared'"/>
<xsl:variable name="tmp_href"><xsl:value-of select="concat($urlpre,'shared/text/shared/00/00000004.xhp',$urlpost)"/></xsl:variable>
<xsl:variable name="tmp_doc" select="document($tmp_href)"/>
<table class="howtoget" width="100%" border="1" cellpadding="3" cellspacing="0">
<tr>
<td>
<p class="howtogetheader"><xsl:apply-templates select="$tmp_doc//variable[@id='wie']"/></p>
<div class="howtogetbody">
<xsl:choose>
<xsl:when test="$linkhref = ''"> <!-- new style -->
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise> <!-- old style -->
<xsl:variable name="archive1"><xsl:value-of select="concat(substring-before(substring-after($linkhref,'text/'),'/'),'/')"/></xsl:variable>
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,$archive1,substring-before($linkhref,'#'),$urlpost)"/></xsl:variable>
<xsl:variable name="anc"><xsl:value-of select="substring-after($linkhref,'#')"/></xsl:variable>
<xsl:variable name="docum" select="document($href)"/>
<xsl:call-template name="insertembed">
<xsl:with-param name="doc" select="$docum" />
<xsl:with-param name="anchor" select="$anc" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</div>
</td>
</tr>
</table>
<br/>
</xsl:template>
<!-- Create a link -->
<xsl:template name="createlink">
<xsl:variable name="archive"><xsl:value-of select="concat(substring-before(substring-after(@href,'text/'),'/'),'/')"/></xsl:variable>
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="$archive"/></xsl:call-template></xsl:variable>
<xsl:choose>
<xsl:when test="starts-with(@href,'http://') or starts-with(@href,'https://')"> <!-- web links -->
<a href="{@href}"><xsl:apply-templates /></a>
</xsl:when>
<xsl:when test="contains(@href,'#')">
<xsl:variable name="anchor"><xsl:value-of select="concat('#',substring-after(@href,'#'))"/></xsl:variable>
<xsl:variable name="href"><xsl:value-of select="concat($linkprefix,$archive,substring-before(@href,'#'),$linkpostfix,$dbpostfix,$anchor)"/></xsl:variable>
<a href="{$href}"><xsl:apply-templates /></a>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="href"><xsl:value-of select="concat($linkprefix,$archive,@href,$linkpostfix,$dbpostfix)"/></xsl:variable>
<a href="{$href}"><xsl:apply-templates /></a>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Insert Note, Warning, or Tip -->
<xsl:template name="insertnote">
<xsl:param name="type" /> <!-- note, tip, or warning -->
<xsl:variable name="imgsrc">
<xsl:choose>
<xsl:when test="$type='note'"><xsl:value-of select="$note_img"/></xsl:when>
<xsl:when test="$type='tip'"><xsl:value-of select="$tip_img"/></xsl:when>
<xsl:when test="$type='warning'"><xsl:value-of select="$warning_img"/></xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="'shared'"/></xsl:call-template></xsl:variable>
<xsl:variable name="alt">
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,'shared/',$alttext,$urlpost,$dbpostfix)"/></xsl:variable>
<xsl:variable name="anchor"><xsl:value-of select="concat('alt_',$type)"/></xsl:variable>
<xsl:variable name="doc" select="document($href)"/>
<xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
</xsl:variable>
<div class="{$type}">
<table border="0" class="{$type}" cellspacing="0" cellpadding="5">
<tr>
<td><img src="{$imgsrc}" alt="{$alt}" title="{$alt}"/></td>
<td><xsl:apply-templates /></td>
</tr>
</table>
</div>
<br/>
</xsl:template>
<!-- Insert a heading -->
<xsl:template name="insertheading">
<xsl:param name="level" />
<xsl:param name="embedded" />
<xsl:text disable-output-escaping="yes">&lt;h</xsl:text><xsl:value-of select="$level"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
<xsl:text disable-output-escaping="yes">&lt;/h</xsl:text><xsl:value-of select="$level"/><xsl:text disable-output-escaping="yes">&gt;</xsl:text>
</xsl:template>
<!-- Evaluate a case or caseinline switch -->
<xsl:template name="insertcase">
<xsl:param name="embedded" />
<xsl:choose>
<xsl:when test="parent::switch[@select='sys'] or parent::switchinline[@select='sys']">
<xsl:if test="@select = $System">
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
<xsl:when test="parent::switch[@select='appl'] or parent::switchinline[@select='appl']">
<xsl:if test="@select = $appl">
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
<xsl:when test="parent::switch[@select='distrib'] or parent::switchinline[@select='distrib']">
<xsl:if test="@select = $distrib">
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- Evaluate a default or defaultinline switch -->
<xsl:template name="insertdefault">
<xsl:param name="embedded" />
<xsl:choose>
<xsl:when test="parent::switch[@select='sys'] or parent::switchinline[@select='sys']">
<xsl:if test="not(../child::case[@select=$System]) and not(../child::caseinline[@select=$System])">
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
<xsl:when test="parent::switch[@select='appl'] or parent::switchinline[@select='appl']">
<xsl:if test="not(../child::case[@select=$appl]) and not(../child::caseinline[@select=$appl])">
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
<xsl:when test="parent::switch[@select='distrib'] or parent::switchinline[@select='distrib']">
<xsl:if test="not(../child::case[@select=$distrib]) and not(../child::caseinline[@select=$distrib])">
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
<!-- evaluate embeds -->
<xsl:template name="insertembed">
<xsl:param name="doc" />
<xsl:param name="anchor" />
<!-- different embed targets (also falsely used embed instead embedvar) -->
<xsl:choose>
<xsl:when test="$doc//section[@id=$anchor]"> <!-- first test for a section of that name -->
<xsl:apply-templates select="$doc//section[@id=$anchor]" mode="embedded"/>
</xsl:when>
<xsl:when test="$doc//paragraph[@id=$anchor]"> <!-- then test for a para of that name -->
<p class="embedded">
<xsl:apply-templates select="$doc//paragraph[@id=$anchor]" mode="embedded"/>
</p>
</xsl:when>
<xsl:when test="$doc//variable[@id=$anchor]"> <!-- then test for a variable of that name -->
<p class="embedded">
<xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
</p>
</xsl:when>
<xsl:otherwise> <!-- then give up -->
<p class="bug">D'oh! You found a bug (<xsl:value-of select="@href"/> not found).</p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Insert an image -->
<xsl:template name="insertimage">
<xsl:variable name="fpath">
<xsl:call-template name="getfpath">
<xsl:with-param name="s"><xsl:value-of select="@src"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="fname">
<xsl:call-template name="getfname">
<xsl:with-param name="s"><xsl:value-of select="@src"/></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="src">
<xsl:choose>
<xsl:when test="not($ExtensionId='') and starts-with(@src,$ExtensionId)">
<xsl:value-of select="concat($ExtensionPath,'/',@src)"/>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="(@localize='true') and not($lang='en-US')">
<xsl:value-of select="concat($img_url_prefix,$fpath,$lang,'/',$fname)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat($img_url_prefix,$fpath,$fname)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!--<xsl:variable name="src"><xsl:value-of select="concat($img_url_prefix,@src)"/></xsl:variable>-->
<xsl:variable name="alt"><xsl:value-of select="./alt"/></xsl:variable>
<xsl:variable name="width" select="''"/> <!-- Images don't all have the correct size -->
<xsl:variable name="height" select="''"/><!-- Image don't all have the correct size -->
<img src="{$src}" alt="{$alt}" title="{$alt}">
<xsl:if test="not($width='')"><xsl:attribute name="width"><xsl:value-of select="$width"/></xsl:attribute></xsl:if>
<xsl:if test="not($height='')"><xsl:attribute name="height"><xsl:value-of select="$height"/></xsl:attribute></xsl:if>
</img>
</xsl:template>
<!-- Insert a Table -->
<xsl:template name="inserttable">
<xsl:variable name="imgsrc"> <!-- see if we are in an image table -->
<xsl:value-of select="tablerow/tablecell[1]/paragraph[1]/image/@src"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="count(descendant::tablecell)=1">
<table border="0" class="onecell" cellpadding="0" cellspacing="0">
<xsl:apply-templates />
</table>
</xsl:when>
<xsl:when test="descendant::tablecell[1]/descendant::image">
<table border="0" class="icontable" cellpadding="5" cellspacing="0">
<xsl:apply-templates mode="icontable"/>
</table>
</xsl:when>
<xsl:when test="@class='wide'">
<table border="1" class="{@class}" cellpadding="0" cellspacing="0" width="100%" >
<xsl:apply-templates />
</table>
</xsl:when>
<xsl:when test="not(@class='')">
<table border="1" class="{@class}" cellpadding="0" cellspacing="0" >
<xsl:apply-templates />
</table>
</xsl:when>
<xsl:otherwise>
<table border="1" class="border" cellpadding="0" cellspacing="0" >
<xsl:apply-templates />
</table>
</xsl:otherwise>
</xsl:choose>
<br/>
</xsl:template>
<xsl:template name="resolveembed">
<div class="embedded">
<xsl:variable name="archive"><xsl:value-of select="concat(substring-before(substring-after(@href,'text/'),'/'),'/')"/></xsl:variable>
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="$archive"/></xsl:call-template></xsl:variable>
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,$archive,substring-before(@href,'#'),$urlpost,$dbpostfix)"/></xsl:variable>
<xsl:variable name="anc"><xsl:value-of select="substring-after(@href,'#')"/></xsl:variable>
<xsl:variable name="docum" select="document($href)"/>
<xsl:call-template name="insertembed">
<xsl:with-param name="doc" select="$docum" />
<xsl:with-param name="anchor" select="$anc" />
</xsl:call-template>
</div>
</xsl:template>
<xsl:template name="resolveembedvar">
<xsl:if test="not(@href='text/shared/00/00000004.xhp#wie')"> <!-- special treatment if howtoget links -->
<xsl:variable name="archive"><xsl:value-of select="concat(substring-before(substring-after(@href,'text/'),'/'),'/')"/></xsl:variable>
<xsl:variable name="dbpostfix"><xsl:call-template name="createDBpostfix"><xsl:with-param name="archive" select="$archive"/></xsl:call-template></xsl:variable>
<xsl:variable name="href"><xsl:value-of select="concat($urlpre,$archive,substring-before(@href,'#'),$urlpost,$dbpostfix)"/></xsl:variable>
<xsl:variable name="anchor"><xsl:value-of select="substring-after(@href,'#')"/></xsl:variable>
<xsl:variable name="doc" select="document($href)"/>
<xsl:choose>
<xsl:when test="$doc//variable[@id=$anchor]"> <!-- test for a variable of that name -->
<xsl:apply-templates select="$doc//variable[@id=$anchor]" mode="embedded"/>
</xsl:when>
<xsl:otherwise> <!-- or give up -->
<span class="bug">[<xsl:value-of select="@href"/> not found].</span>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<!-- Apply -->
<xsl:template name="apply">
<xsl:param name="embedded" />
<xsl:choose>
<xsl:when test="$embedded = 'yes'">
<xsl:apply-templates mode="embedded"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="getfpath">
<xsl:param name="s"/>
<xsl:param name="p"/>
<xsl:choose>
<xsl:when test="contains($s,'/')">
<xsl:call-template name="getfpath">
<xsl:with-param name="p"><xsl:value-of select="concat($p,substring-before($s,'/'),'/')"/></xsl:with-param>
<xsl:with-param name="s"><xsl:value-of select="substring-after($s,'/')"/></xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$p"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="getfname">
<xsl:param name="s"/>
<xsl:choose>
<xsl:when test="contains($s,'/')">
<xsl:call-template name="getfname">
<xsl:with-param name="s"><xsl:value-of select="substring-after($s,'/')"/></xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$s"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="createDBpostfix">
<xsl:param name="archive"/>
<xsl:variable name="newDB">
<xsl:choose>
<xsl:when test="(substring($archive,1,6) = 'shared')"><xsl:value-of select="$Database"/></xsl:when>
<xsl:otherwise><xsl:value-of select="substring-before($archive,'/')"/></xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="concat($am,'DbPAR=',$newDB)"/>
</xsl:template>
</xsl:stylesheet>

View File

@@ -0,0 +1,94 @@
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ OPENOFFICE.ORG 2.0 HELP +
+ DEFAULT STYLESHEET +
+ CHINESE SIMPL +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ LAST CHANGES: 24-MAR-2005 +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ font-family: ,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
{ font-family: ,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
.acronym
{ font-weight: bold; }
.related
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
.emph, .menuitem, .keycode
{ font-weight: bold; }
.tablehead, .tableheadintable
{ font-weight: bold; margin-top: 0px;}
.howtogetheader
{ font-weight: bold; border: 1px solid #999999; background: #FFFFFF; padding: 3px;}
h1, h2, h3, h4, h5, h6
{ margin-bottom: 5pt; }
p, td
{ font-size: 10pt; }
h1
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
h2
{ font-size: 14pt; }
h3
{ font-size: 12pt; }
h4, h5, h6
{ font-size: 10pt; }
.relatedtopics
{ font-weight: normal; }
.relatedbody
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
.howtoget
{ background:#EEEEEE;}
.howtogetbody
{ background:#EEEEEE;}
.wide
{ width: 100%; }
.topalign
{ vertical-align: top; border: 1px;}
.bug
{ color: red; border: 1px solid red;}
.debug
{ border: 1px solid black; padding: 3px; display: none;}

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--***********************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
***********************************************************-->
<helpdocument version="1.0">
<meta>
<topic id="textshared05err_htmlxml" indexer="exclude" status="PUBLISH">
<title id="tit" xml-lang="zh-CN">未找到帮助页面</title>
<filename>/text/shared/05/err_html.xhp</filename>
</topic>
<history>
<created date="2003-10-31T00:00:00">Sun Microsystems, Inc.</created>
<lastedited date="2005-01-11T11:07:13">converted from old format - fpe
FPE: Updated</lastedited>
</history>
</meta>
<body>
<paragraph role="heading" id="hd_id3146957" xml-lang="zh-CN" level="1" l10n="U" oldref="1">帮助页面未能找到。</paragraph>
<paragraph role="paragraph" id="par_id3147088" xml-lang="zh-CN" l10n="U" oldref="2">很遗憾,您所选择的帮助页面未能找到。以下数据可能对界定错误有所帮助:</paragraph>
<paragraph role="paragraph" id="par_id3143268" xml-lang="zh-CN" l10n="U" oldref="3">帮助 ID<emph><help-id-missing/></emph></paragraph>
<paragraph role="paragraph" id="par_idN10681" xml-lang="zh-CN" l10n="NEW">可以使用安装应用程序来安装缺少的帮助模块。</paragraph>
<paragraph role="paragraph" id="par_id3150541" xml-lang="zh-CN" l10n="U" oldref="16">单击<image id="img_id3148946" src="res/sc06301.png" width="0.222inch" height="0.222inch"><alt id="alt_id3148946">图标</alt></image><emph>上一步</emph>可返回上一页面。</paragraph>
</body>
</helpdocument>

View File

@@ -0,0 +1,114 @@
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ OPENOFFICE.ORG 2.0 HELP +
+ HIGH CONTRAST #1 STYLESHEET +
+ CHINESE SIMPL +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ LAST CHANGES: 24-MAR-2005 +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ font-family: ,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
{ font-family: ,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
.acronym
{ font-weight: bold; }
.related
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
.emph, .menuitem, .keycode
{ font-weight: bold; }
.tablehead, .tableheadintable
{ font-weight: bold; margin-top: 0px;}
.howtogetheader
{ font-weight: bold; padding: 3px;}
h1, h2, h3, h4, h5, h6
{ margin-bottom: 5pt; }
p, td
{ font-size: 10pt; }
h1
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
h2
{ font-size: 14pt; }
h3
{ font-size: 12pt; }
h4, h5, h6
{ font-size: 10pt; }
.relatedtopics
{ font-weight: normal; }
.relatedbody
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
.wide
{ width: 100%; }
.topalign
{ vertical-align: top; border: 1px;}
.bug
{ color: red; border: 1px solid red;}
.debug
{ border: 1px solid black; padding: 3px; display: none;}
/* HIGH CONTRAST SPECIFIC SETTINGS */
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ background: #000000; color: #FFFF00;}
.related
{ border-top: 1px solid #FFFF00; }
.howtogetheader
{border: 1px solid #EFEFEF; background: #000000;}
h1
{ border-bottom: 1px solid #FFFF00; ]
.howtoget
{ background:#000000;}
.howtogetbody
{ background:#000000;}
.debug
{ border: 1px solid red; padding: 3px; display: none;}
a
{ color: #FFFF00; }

View File

@@ -0,0 +1,114 @@
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ OPENOFFICE.ORG 2.0 HELP +
+ HIGH CONTRAST #2 STYLESHEET +
+ CHINESE SIMPL +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ LAST CHANGES: 24-MAR-2005 +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ font-family: ,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
{ font-family: ,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
.acronym
{ font-weight: bold; }
.related
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
.emph, .menuitem, .keycode
{ font-weight: bold; }
.tablehead, .tableheadintable
{ font-weight: bold; margin-top: 0px;}
.howtogetheader
{ font-weight: bold; padding: 3px;}
h1, h2, h3, h4, h5, h6
{ margin-bottom: 5pt; }
p, td
{ font-size: 10pt; }
h1
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
h2
{ font-size: 14pt; }
h3
{ font-size: 12pt; }
h4, h5, h6
{ font-size: 10pt; }
.relatedtopics
{ font-weight: normal; }
.relatedbody
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
.wide
{ width: 100%; }
.topalign
{ vertical-align: top; border: 1px;}
.bug
{ color: red; border: 1px solid red;}
.debug
{ border: 1px solid black; padding: 3px; display: none;}
/* HIGH CONTRAST SPECIFIC SETTINGS */
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ background: #000000; color: #00FF00;}
.related
{ border-top: 1px solid #00FF00; }
.howtogetheader
{border: 1px solid #EFEFEF; background: #000000;}
h1
{ border-bottom: 1px solid #00FF00; ]
.howtoget
{ background:#000000;}
.howtogetbody
{ background:#000000;}
.debug
{ border: 1px solid red; padding: 3px; display: none;}
a
{ color: #00FF00; }

View File

@@ -0,0 +1,114 @@
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ OPENOFFICE.ORG 2.0 HELP +
+ HIGH CONTRAST BLACK STYLESHEET +
+ CHINESE SIMPL +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ LAST CHANGES: 24-MAR-2005 +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ font-family: ,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
{ font-family: ,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
.acronym
{ font-weight: bold; }
.related
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
.emph, .menuitem, .keycode
{ font-weight: bold; }
.tablehead, .tableheadintable
{ font-weight: bold; margin-top: 0px;}
.howtogetheader
{ font-weight: bold; padding: 3px;}
h1, h2, h3, h4, h5, h6
{ margin-bottom: 5pt; }
p, td
{ font-size: 10pt; }
h1
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
h2
{ font-size: 14pt; }
h3
{ font-size: 12pt; }
h4, h5, h6
{ font-size: 10pt; }
.relatedtopics
{ font-weight: normal; }
.relatedbody
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
.wide
{ width: 100%; }
.topalign
{ vertical-align: top; border: 1px;}
.bug
{ color: red; border: 1px solid red;}
.debug
{ border: 1px solid black; padding: 3px; display: none;}
/* HIGH CONTRAST SPECIFIC SETTINGS */
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ background: #000000; color: #FFFFFF;}
.related
{ border-top: 1px solid #FFFFFF; }
.howtogetheader
{border: 1px solid #FFFFFF; background: #000000;}
h1
{ border-bottom: 1px solid #FFFFFF; ]
.howtoget
{ background:#000000;}
.howtogetbody
{ background:#000000;}
.debug
{ border: 1px solid red; padding: 3px; display: none;}
a
{ color: #FFFFFF; }

View File

@@ -0,0 +1,114 @@
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
/*
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ OPENOFFICE.ORG 2.0 HELP +
+ HIGH CONTRAST WHITE STYLESHEET +
+ CHINESE SIMPL +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ LAST CHANGES: 24-MAR-2005 +
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
*/
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ font-family: ,"MSung Light SC",SimSun,FZSongYi,FZShuSong,NSimSun,"Andale Sans UI","Arial Unicode MS","Lucida Sans Unicode",Song; }
.code, .codeintable, .example, .exampleintable, .literal, .literalintable, .path, .pathintable
{ font-family: ,"MSung Light SC",Cumberland,Courier New,Courier,"Lucida Sans Typewriter","Lucida Typewriter",Monaco,Monospaced; margin-top: 1pt; margin-bottom: 1pt;}
.acronym
{ font-weight: bold; }
.related
{ font-weight: bold; margin-top:20pt; border-top: 1px solid black;}
.emph, .menuitem, .keycode
{ font-weight: bold; }
.tablehead, .tableheadintable
{ font-weight: bold; margin-top: 0px;}
.howtogetheader
{ font-weight: bold; padding: 3px;}
h1, h2, h3, h4, h5, h6
{ margin-bottom: 5pt; }
p, td
{ font-size: 10pt; }
h1
{ font-size: 18pt; border-bottom: 1px solid black; padding-bottom: 6px; margin-bottom: 6px;}
h2
{ font-size: 14pt; }
h3
{ font-size: 12pt; }
h4, h5, h6
{ font-size: 10pt; }
.relatedtopics
{ font-weight: normal; }
.relatedbody
{ margin-top: 2px; margin-bottom: 2px; margin-left: 5px; }
.wide
{ width: 100%; }
.topalign
{ vertical-align: top; border: 1px;}
.bug
{ color: red; border: 1px solid red;}
.debug
{ border: 1px solid black; padding: 3px; display: none;}
/* HIGH CONTRAST SPECIFIC SETTINGS */
body, p, h1, h2, h3, h4, h5, h6, .listitem, .listitemintable, .tablecontent, .tablecontentintable
{ background: #FFFFFF; color: #000000;}
.related
{ border-top: 1px solid #000000; }
.howtogetheader
{border: 1px solid #000000; background: #FFFFFF;}
h1
{ border-bottom: 1px solid #000000; ]
.howtoget
{ background:#FFFFFF;}
.howtogetbody
{ background:#FFFFFF;}
.debug
{ border: 1px solid red; padding: 3px; display: none;}
a
{ color: #000000; }

View File

@@ -0,0 +1,30 @@
###############################################################
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
###############################################################
Title=%PRODUCTNAME Basic
Language=zh-CN
Order=7
Start=text%2Fsbasic%2Fshared%2Fmain0601.xhp
Heading=headingheading
Program=BASIC
07.07.04 00:00:00

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,265 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--***********************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
***********************************************************-->
<tree_view version="24-Aug-2004">
<help_section application="sbasic" id="07" title="宏和编程">
<node id="0701" title="一般信息和用户界面的使用">
<topic id="sbasic/text/sbasic/shared/main0601.xhp">%PRODUCTNAME Basic 帮助</topic>
<topic id="sbasic/text/sbasic/shared/01000000.xhp">使用 %PRODUCTNAME Basic 编程</topic>
<topic id="sbasic/text/sbasic/shared/00000002.xhp">%PRODUCTNAME Basic 词汇表</topic>
<topic id="sbasic/text/sbasic/shared/01010210.xhp">Basics</topic>
<topic id="sbasic/text/sbasic/shared/01020000.xhp">语法</topic>
<topic id="sbasic/text/sbasic/shared/01050000.xhp">%PRODUCTNAME Basic IDE</topic>
<topic id="sbasic/text/sbasic/shared/01030100.xhp">IDE 概况</topic>
<topic id="sbasic/text/sbasic/shared/01030200.xhp">Basic 编辑器</topic>
<topic id="sbasic/text/sbasic/shared/01050100.xhp">监视窗口</topic>
<topic id="sbasic/text/sbasic/shared/main0211.xhp">宏工具栏</topic>
<topic id="sbasic/text/sbasic/shared/05060700.xhp">宏</topic>
</node>
<node id="0702" title="命令引用">
<topic id="sbasic/text/sbasic/shared/01020300.xhp">使用过程和函数</topic>
<topic id="sbasic/text/sbasic/shared/01020500.xhp">程序库、模块和对话框</topic>
<node id="070202" title="运行时函数、语句和运算符">
<topic id="sbasic/text/sbasic/shared/03010000.xhp">屏幕 I/O 函数</topic>
<topic id="sbasic/text/sbasic/shared/03020000.xhp">文件 I/O 函数</topic>
<topic id="sbasic/text/sbasic/shared/03030000.xhp">日期和时间函数</topic>
<topic id="sbasic/text/sbasic/shared/03050000.xhp">错误处理函数</topic>
<topic id="sbasic/text/sbasic/shared/03060000.xhp">逻辑运算符</topic>
<topic id="sbasic/text/sbasic/shared/03070000.xhp">数学运算符</topic>
<topic id="sbasic/text/sbasic/shared/03080000.xhp">数字函数</topic>
<topic id="sbasic/text/sbasic/shared/03090000.xhp">控制程序的执行</topic>
<topic id="sbasic/text/sbasic/shared/03100000.xhp">变量</topic>
<topic id="sbasic/text/sbasic/shared/03110000.xhp">比较运算符</topic>
<topic id="sbasic/text/sbasic/shared/03120000.xhp">字符串</topic>
<topic id="sbasic/text/sbasic/shared/03130000.xhp">其他命令</topic>
</node>
<node id="070201" title="函数、语句和运算符的字母顺序列表">
<topic id="sbasic/text/sbasic/shared/03080601.xhp">Abs 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03060100.xhp">AND 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03104200.xhp">Array 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120101.xhp">Asc 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080101.xhp">Atn 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03130100.xhp">Beep 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010301.xhp">Blue 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03100100.xhp">CBool 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120105.xhp">CByte 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030108.xhp">CDateFromIso 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030107.xhp">CdateToIso 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03100300.xhp">CDate 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03100400.xhp">CDbl 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03100500.xhp">CInt 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03100600.xhp">CLng 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03100900.xhp">CSng 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03101000.xhp">CStr 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090401.xhp">Call 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020401.xhp">ChDir 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020402.xhp">ChDrive 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090402.xhp">Choose 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120102.xhp">Chr 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020101.xhp">Close 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03110100.xhp">比较运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03100700.xhp">Const 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120313.xhp">ConvertFromURL 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120312.xhp">ConvertToURL 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080102.xhp">Cos 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131800.xhp">CreateUnoDialog 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03132000.xhp">CreateUnoListener 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131600.xhp">CreateUnoService 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131500.xhp">CreateUnoStruct 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020403.xhp">CurDir 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030101.xhp">DateSerial 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030102.xhp">DateValue 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030301.xhp">Date 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030103.xhp">Day 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090403.xhp">Declare 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03101100.xhp">DefBool 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03101300.xhp">DefDate 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03101400.xhp">DefDbl 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03101500.xhp">DefInt 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03101600.xhp">DefLng 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03101700.xhp">DefObj 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102000.xhp">DefVar 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03104300.xhp">DimArray 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102100.xhp">Dim 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020404.xhp">Dir 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090201.xhp">Do...Loop 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03110100.xhp">比较运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090404.xhp">End 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03130800.xhp">Environ 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020301.xhp">Eof 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03104600.xhp">EqualUnoObjects 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03060200.xhp">Eqv 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03050100.xhp">Erl 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03050200.xhp">Err 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03050300.xhp">Error 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03050000.xhp">错误处理函数</topic>
<topic id="sbasic/text/sbasic/shared/03090412.xhp">Exit 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080201.xhp">Exp 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020405.xhp">FileAttr 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020406.xhp">FileCopy 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020407.xhp">FileDateTime 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020415.xhp">FileExists 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020408.xhp">FileLen 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103800.xhp">FindObject 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103900.xhp">FindPropertyObject 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080501.xhp">Fix 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090202.xhp">For...Next 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120301.xhp">Format 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020102.xhp">FreeFile 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090405.xhp">FreeLibrary 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090406.xhp">Function 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090400.xhp">其他语句</topic>
<topic id="sbasic/text/sbasic/shared/03080300.xhp">生成随机数</topic>
<topic id="sbasic/text/sbasic/shared/03020409.xhp">GetAttr 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131700.xhp">GetProcessServiceManager 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131000.xhp">GetSolarVersion 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03130700.xhp">GetSystemTicks 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020201.xhp">Get 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131900.xhp">GlobalScope [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090301.xhp">GoSub...Return 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090302.xhp">GoTo 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010302.xhp">Green 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03104400.xhp">HasUnoInterfaces 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080801.xhp">Hex 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030201.xhp">Hour 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090103.xhp">IIf 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090101.xhp">If...Then...Else 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03060300.xhp">隐含运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120401.xhp">InStr 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010201.xhp">InputBox 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020202.xhp">Input# 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080502.xhp">Int 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102200.xhp">IsArray 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102300.xhp">IsDate 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102400.xhp">IsEmpty 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03104000.xhp">IsMissing 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102600.xhp">IsNull 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102700.xhp">IsNumeric 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102800.xhp">IsObject 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03104500.xhp">IsUnoStruct 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120315.xhp">Join 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020410.xhp">Kill 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102900.xhp">LBound 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120302.xhp">LCase 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120304.xhp">LSet 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120305.xhp">LTrim 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120303.xhp">Left 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120402.xhp">Len 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103100.xhp">Let 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020203.xhp">Line Input # 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020302.xhp">Loc 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020303.xhp">Lof 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080202.xhp">Log 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120306.xhp">Mid 函数、Mid 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030202.xhp">Minute 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020411.xhp">MkDir 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03070600.xhp">Mod 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030104.xhp">Month 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010102.xhp">MsgBox 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010101.xhp">MsgBox 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020412.xhp">Name 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03060400.xhp">"Not"运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030203.xhp">Now 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080000.xhp">数字函数</topic>
<topic id="sbasic/text/sbasic/shared/03080802.xhp">Oct 函数 [运行时间]</topic>
<topic id="sbasic/text/sbasic/shared/03050500.xhp">On Error GoTo ...Resume 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090303.xhp">On...GoSub 语句On...GoTo 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020103.xhp">Open 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103200.xhp">Option Base 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103300.xhp">Option Explicit 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03104100.xhp">Optional在函数语句中[运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03060500.xhp">Or 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010103.xhp">Print 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103400.xhp">Public 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020204.xhp">Put 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010304.xhp">QBColor 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010305.xhp">RGB 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120308.xhp">RSet 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120309.xhp">RTrim 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080301.xhp">Randomize 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03102101.xhp">ReDim 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03010303.xhp">Red 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090407.xhp">Rem 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020104.xhp">Reset 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120307.xhp">Right 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020413.xhp">RmDir 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080302.xhp">Rnd 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030204.xhp">Second 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020304.xhp">Seek 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020305.xhp">Seek 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090102.xhp">Select...Case 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020414.xhp">SetAttr 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103700.xhp">Set 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080701.xhp">Sgn 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03130500.xhp">Shell 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080103.xhp">Sin 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120201.xhp">Space 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120314.xhp">Split 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080401.xhp">Sqr 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080400.xhp">计算平方根</topic>
<topic id="sbasic/text/sbasic/shared/03103500.xhp">Static 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090408.xhp">Stop 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120403.xhp">StrComp 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120103.xhp">Str 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120202.xhp">String 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090409.xhp">Sub 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090410.xhp">Switch 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080104.xhp">Tan 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030205.xhp">TimeSerial 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030206.xhp">TimeValue 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030302.xhp">Time 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030303.xhp">Timer 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03080100.xhp">三角函数</topic>
<topic id="sbasic/text/sbasic/shared/03120311.xhp">Trim 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131300.xhp">TwipsPerPixelX 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03131400.xhp">TwipsPerPixelY 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103600.xhp">TypeName 函数; VarType 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03103000.xhp">UBound 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120310.xhp">UCase 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03120104.xhp">Val 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03130600.xhp">Wait 语句 [运行时间]</topic>
<topic id="sbasic/text/sbasic/shared/03030105.xhp">WeekDay 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090203.xhp">While...Wend 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03090411.xhp">With 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03020205.xhp">Write 语句 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03060600.xhp">Xor 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03030106.xhp">Year 函数 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03070100.xhp">"-" 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03070200.xhp">"*" 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03070300.xhp">"+" 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03070400.xhp">"/" 运算符 [运行时]</topic>
<topic id="sbasic/text/sbasic/shared/03070500.xhp">"^" 运算符 [运行时]</topic>
</node>
</node>
<node id="0703" title="指南">
<topic id="sbasic/text/sbasic/guide/control_properties.xhp">修改对话框编辑器中控件的属性</topic>
<topic id="sbasic/text/sbasic/guide/insert_control.xhp">在对话框编辑器中创建控件</topic>
<topic id="sbasic/text/sbasic/guide/sample_code.xhp">对话框编辑器中控件的编程示例</topic>
<topic id="sbasic/text/sbasic/guide/show_dialog.xhp">通过程序代码打开对话框</topic>
<topic id="sbasic/text/sbasic/guide/create_dialog.xhp">创建 Basic 对话框</topic>
<topic id="sbasic/text/sbasic/shared/01030400.xhp">管理库和模块</topic>
<topic id="sbasic/text/sbasic/shared/01020100.xhp">使用变量</topic>
<topic id="sbasic/text/sbasic/shared/01020200.xhp">使用对象</topic>
<topic id="sbasic/text/sbasic/shared/01030300.xhp">调试 Basic 程序</topic>
<topic id="sbasic/text/sbasic/shared/01040000.xhp">事件驱动的宏</topic>
</node>
</help_section>
</tree_view>

View File

@@ -0,0 +1,30 @@
###############################################################
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
###############################################################
Title=%PRODUCTNAME Calc
Language=zh-CN
Order=3
Start=text%2Fscalc%2Fmain0000.xhp
Heading=headingheading
Program=CALC
07.07.04 00:00:00

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--***********************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
***********************************************************-->
<tree_view version="24-Aug-2004">
<help_section application="scalc" id="08" title="电子表格">
<node id="0801" title="一般信息和用户界面的使用">
<topic id="scalc/text/scalc/main0000.xhp">欢迎使用 %PRODUCTNAME Calc 帮助</topic>
<topic id="scalc/text/scalc/main0503.xhp">%PRODUCTNAME Calc 功能</topic>
<topic id="scalc/text/scalc/guide/keyboard.xhp">快捷键(%PRODUCTNAME Calc 辅助功能)</topic>
<topic id="scalc/text/scalc/04/01020000.xhp">电子表格的快捷键</topic>
<topic id="scalc/text/scalc/05/02140000.xhp">%PRODUCTNAME Calc 中的错误代码</topic>
<topic id="scalc/text/scalc/01/04060112.xhp">%PRODUCTNAME Calc 中用于编程的加载宏</topic>
<topic id="scalc/text/scalc/guide/main.xhp">%PRODUCTNAME Calc 使用说明</topic>
</node>
<node id="0802" title="命令和菜单引用">
<node id="080201" title="菜单">
<topic id="scalc/text/scalc/main0100.xhp">菜单</topic>
<topic id="scalc/text/scalc/main0101.xhp">文件</topic>
<topic id="scalc/text/scalc/main0102.xhp">编辑</topic>
<topic id="scalc/text/scalc/main0103.xhp">视图</topic>
<topic id="scalc/text/scalc/main0104.xhp">插入</topic>
<topic id="scalc/text/scalc/main0105.xhp">格式</topic>
<topic id="scalc/text/scalc/main0106.xhp">工具</topic>
<topic id="scalc/text/scalc/main0107.xhp">窗口</topic>
<topic id="scalc/text/scalc/main0112.xhp">数据</topic>
</node>
<node id="080202" title="工具栏">
<topic id="scalc/text/scalc/main0200.xhp">工具栏</topic>
<topic id="scalc/text/scalc/main0202.xhp">格式栏</topic>
<topic id="scalc/text/scalc/main0203.xhp">绘图对象属性栏</topic>
<topic id="scalc/text/scalc/main0205.xhp">文字格式栏</topic>
<topic id="scalc/text/scalc/main0206.xhp">公式栏</topic>
<topic id="scalc/text/scalc/main0208.xhp">状态栏</topic>
<topic id="scalc/text/scalc/main0210.xhp">打印预览栏</topic>
<topic id="scalc/text/scalc/main0214.xhp">图片栏</topic>
<topic id="scalc/text/scalc/main0218.xhp">工具栏</topic>
<topic id="shared/text/shared/main0201.xhp">标准栏</topic>
<topic id="shared/text/shared/main0209.xhp">超链接地址栏</topic>
<topic id="shared/text/shared/main0212.xhp">表格数据栏</topic>
<topic id="shared/text/shared/main0213.xhp">窗体导航栏</topic>
<topic id="shared/text/shared/main0214.xhp">查询设计栏</topic>
<topic id="shared/text/shared/main0226.xhp">窗体设计工具栏</topic>
</node>
</node>
<node id="0803" title="函数类型和运算符">
<topic id="scalc/text/scalc/01/04060000.xhp">函数向导</topic>
<topic id="scalc/text/scalc/01/04060100.xhp">函数(按类别)</topic>
<topic id="scalc/text/scalc/01/04060101.xhp">数据库函数</topic>
<topic id="scalc/text/scalc/01/04060102.xhp">日期和时间函数</topic>
<topic id="scalc/text/scalc/01/04060103.xhp">财务函数第一部分</topic>
<topic id="scalc/text/scalc/01/04060119.xhp">财务函数第二部分</topic>
<topic id="scalc/text/scalc/01/04060118.xhp">金融函数第三部分</topic>
<topic id="scalc/text/scalc/01/04060104.xhp">信息函数</topic>
<topic id="scalc/text/scalc/01/04060105.xhp">逻辑函数</topic>
<topic id="scalc/text/scalc/01/04060106.xhp">数学函数</topic>
<topic id="scalc/text/scalc/01/04060107.xhp">矩阵函数</topic>
<topic id="scalc/text/scalc/01/04060108.xhp">统计函数</topic>
<topic id="scalc/text/scalc/01/04060181.xhp">统计函数第一部分</topic>
<topic id="scalc/text/scalc/01/04060182.xhp">统计函数第二部分</topic>
<topic id="scalc/text/scalc/01/04060183.xhp">统计函数第三部分</topic>
<topic id="scalc/text/scalc/01/04060184.xhp">统计函数第四部分</topic>
<topic id="scalc/text/scalc/01/04060185.xhp">统计函数第五部分</topic>
<topic id="scalc/text/scalc/01/04060109.xhp">电子表格函数</topic>
<topic id="scalc/text/scalc/01/04060110.xhp">文字函数</topic>
<topic id="scalc/text/scalc/01/04060111.xhp">加载宏函数</topic>
<topic id="scalc/text/scalc/01/04060115.xhp">加载宏函数,分析函数列表第一部分</topic>
<topic id="scalc/text/scalc/01/04060116.xhp">加载宏函数,分析函数列表第二部分</topic>
<topic id="scalc/text/scalc/01/04060199.xhp">%PRODUCTNAME Calc 中的运算符</topic>
<topic id="scalc/text/scalc/guide/userdefined_function.xhp">自定义函数</topic>
</node>
<node id="0804" title="加载、保存、导入和导出">
<topic id="scalc/text/scalc/guide/webquery.xhp">在表格中插入外部数据 (WebQuery)</topic>
<topic id="scalc/text/scalc/guide/html_doc.xhp">将工作表以 HTML 格式保存和打开</topic>
<topic id="scalc/text/scalc/guide/csv_formula.xhp">导入和导出文本文件</topic>
</node>
<node id="0805" title="格式化">
<topic id="scalc/text/scalc/guide/text_rotate.xhp">旋转文字</topic>
<topic id="scalc/text/scalc/guide/text_wrap.xhp">写入多行文字</topic>
<topic id="scalc/text/scalc/guide/text_numbers.xhp">将数字格式化为文本</topic>
<topic id="scalc/text/scalc/guide/super_subscript.xhp">文字上标/下标</topic>
<topic id="scalc/text/scalc/guide/row_height.xhp">改变行高或列宽</topic>
<topic id="scalc/text/scalc/guide/cellstyle_conditional.xhp">应用条件格式</topic>
<topic id="scalc/text/scalc/guide/cellstyle_minusvalue.xhp">突出显示负数</topic>
<topic id="scalc/text/scalc/guide/cellstyle_by_formula.xhp">根据公式指定的格式</topic>
<topic id="scalc/text/scalc/guide/integer_leading_zero.xhp">输入带前置零的数字</topic>
<topic id="scalc/text/scalc/guide/format_table.xhp">格式化电子表格</topic>
<topic id="scalc/text/scalc/guide/format_value.xhp">格式化带小数的数字</topic>
<topic id="scalc/text/scalc/guide/value_with_name.xhp">命名单元格</topic>
<topic id="scalc/text/scalc/guide/table_rotate.xhp">旋转表格(转置)</topic>
<topic id="scalc/text/scalc/guide/rename_table.xhp">重命名工作表</topic>
<topic id="scalc/text/scalc/guide/year2000.xhp">19xx/20xx 年</topic>
<topic id="scalc/text/scalc/guide/rounding_numbers.xhp">使用四舍五入的数字</topic>
<topic id="scalc/text/scalc/guide/currency_format.xhp">采用货币格式的单元格</topic>
<topic id="scalc/text/scalc/guide/autoformat.xhp">对表格使用自动套用格式</topic>
<topic id="scalc/text/scalc/guide/note_insert.xhp">插入和编辑批注</topic>
<topic id="scalc/text/scalc/guide/design.xhp">选择工作表主题</topic>
<topic id="scalc/text/scalc/guide/fraction_enter.xhp">输入分数</topic>
</node>
<node id="0806" title="筛选和排序">
<topic id="scalc/text/scalc/guide/filters.xhp">应用筛选</topic>
<topic id="scalc/text/scalc/guide/specialfilter.xhp">筛选:应用高级筛选</topic>
<!-- removed scalc/text/scalc/guide/standardfilter.xhp -->
<topic id="scalc/text/scalc/guide/autofilter.xhp">应用自动筛选</topic>
<topic id="scalc/text/scalc/guide/sorted_list.xhp">应用排序列表</topic>
</node>
<node id="0807" title="打印">
<topic id="scalc/text/scalc/guide/print_title_row.xhp">在每一页上打印行或列</topic>
<topic id="scalc/text/scalc/guide/print_landscape.xhp">横向打印工作表</topic>
<topic id="scalc/text/scalc/guide/print_details.xhp">打印工作表详细资料</topic>
<topic id="scalc/text/scalc/guide/print_exact.xhp">定义打印的页数</topic>
</node>
<node id="0808" title="数据区域">
<topic id="scalc/text/scalc/guide/database_define.xhp">定义数据库区域</topic>
<topic id="scalc/text/scalc/guide/database_filter.xhp">过滤单元格范围</topic>
<!-- removed scalc/text/scalc/guide/database_group.xhp -->
<topic id="scalc/text/scalc/guide/database_sort.xhp">数据排序 </topic>
</node>
<node id="0809" title="数据透视表">
<topic id="scalc/text/scalc/guide/datapilot.xhp">数据透视表</topic>
<topic id="scalc/text/scalc/guide/datapilot_createtable.xhp">创建数据透视表</topic>
<topic id="scalc/text/scalc/guide/datapilot_deletetable.xhp">删除数据透视表</topic>
<topic id="scalc/text/scalc/guide/datapilot_edittable.xhp">编辑数据透视表</topic>
<topic id="scalc/text/scalc/guide/datapilot_filtertable.xhp">筛选数据透视表</topic>
<topic id="scalc/text/scalc/guide/datapilot_tipps.xhp">选择数据透视表输出范围</topic>
<topic id="scalc/text/scalc/guide/datapilot_updatetable.xhp">更新数据透视表</topic>
</node>
<node id="0810" title="方案">
<topic id="scalc/text/scalc/guide/scenario.xhp">使用方案</topic>
</node>
<node id="0811" title="引用">
<topic id="scalc/text/scalc/guide/relativ_absolut_ref.xhp">地址和引用,绝对和相对</topic>
<topic id="scalc/text/scalc/guide/cellreferences.xhp">引用其他文档中的单元格</topic>
<topic id="scalc/text/scalc/guide/cellreferences_url.xhp">引用其他工作表和参考 URL</topic>
<topic id="scalc/text/scalc/guide/cellreference_dragdrop.xhp">通过拖放来引用单元格</topic>
<topic id="scalc/text/scalc/guide/address_auto.xhp">寻址时识别名称</topic>
</node>
<node id="0812" title="查看、选择和复制">
<topic id="scalc/text/scalc/guide/table_view.xhp">修改表格视图</topic>
<topic id="scalc/text/scalc/guide/formula_value.xhp">显示公式或数值</topic>
<topic id="scalc/text/scalc/guide/line_fix.xhp">行或列作为标题固定</topic>
<topic id="scalc/text/scalc/guide/multi_tables.xhp">浏览工作表标签</topic>
<topic id="scalc/text/scalc/guide/edit_multitables.xhp">复制到多个工作表</topic>
<topic id="scalc/text/scalc/guide/cellcopy.xhp">仅复制可见单元格</topic>
<topic id="scalc/text/scalc/guide/mark_cells.xhp">选择多个单元格</topic>
</node>
<node id="0813" title="公式和计算">
<topic id="scalc/text/scalc/guide/formulas.xhp">通过公式计算</topic>
<topic id="scalc/text/scalc/guide/formula_copy.xhp">复制公式</topic>
<topic id="scalc/text/scalc/guide/formula_enter.xhp">输入公式</topic>
<topic id="scalc/text/scalc/guide/formula_value.xhp">显示公式或数值</topic>
<topic id="scalc/text/scalc/guide/calculate.xhp">电子表格中的计算</topic>
<topic id="scalc/text/scalc/guide/calc_date.xhp">使用日期和时间进行计算</topic>
<topic id="scalc/text/scalc/guide/calc_series.xhp">自动计算序列</topic>
<topic id="scalc/text/scalc/guide/calc_timevalues.xhp">计算时差</topic>
<topic id="scalc/text/scalc/guide/matrixformula.xhp">输入矩阵公式</topic>
</node>
<node id="0814" title="保护">
<topic id="scalc/text/scalc/guide/cell_protect.xhp">保护单元格不被修改</topic>
<topic id="scalc/text/scalc/guide/cell_unprotect.xhp">取消单元格保护</topic>
</node>
<node id="0815" title="其他">
<!-- removed scalc/text/scalc/guide/autofill.xhp -->
<topic id="scalc/text/scalc/guide/auto_off.xhp">停用自动修改</topic>
<topic id="scalc/text/scalc/guide/consolidate.xhp">合并计算数据</topic>
<topic id="scalc/text/scalc/guide/goalseek.xhp">应用单变量求解</topic>
<topic id="scalc/text/scalc/guide/multioperation.xhp">应用多重计算</topic>
<topic id="scalc/text/scalc/guide/multitables.xhp">应用多个工作表</topic>
<topic id="scalc/text/scalc/guide/validity.xhp">单元格内容的有效性</topic>
</node>
</help_section>
</tree_view>

View File

@@ -0,0 +1,30 @@
###############################################################
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
###############################################################
Title=%PRODUCTNAME Chart
Language=zh-CN
Order=4
Start=text%2Fschart%2Fmain0000.xhp
Heading=headingheading
Program=CHART
07.07.04 00:00:00

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--***********************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
***********************************************************-->
<tree_view version="24-Aug-2004">
<help_section application="scalc" id="05" title="图表和图解">
<node id="0501" title="一般信息">
<topic id="schart/text/schart/main0000.xhp">%PRODUCTNAME 中的图表</topic>
<topic id="schart/text/schart/main0503.xhp">%PRODUCTNAME 图表功能</topic>
<topic id="schart/text/schart/04/01020000.xhp">图表的快捷键</topic>
</node>
</help_section>
</tree_view>

View File

@@ -0,0 +1,30 @@
###############################################################
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
###############################################################
Title=%PRODUCTNAME Base
Language=zh-CN
Order=7
Start=text%2Fshared%2Fexplorer%2Fdatabase%2Fmain.xhp
Heading=headingheading
Program=DATABASE
07.07.04 00:00:00

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
###############################################################
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
###############################################################
Title=%PRODUCTNAME Draw
Language=zh-CN
Order=4
Start=text%2Fsdraw%2Fmain0000.xhp
Heading=headingheading
Program=DRAW
07.07.04 00:00:00

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More