# 一、介绍
前端框架的文件预览功能,实现思路是后端UPMS服务将office文档先转换成pdf文件,前端页面展示PDF文件,后端采用openoffice转换office文档。
目前已知的可以通过openoffice将文档转换为PDF或者HTML以及CSV。其他的转换类型需要自行摸索。
*****
# 二、openoffice安装
[安装包下载地址](http://www.openoffice.org/download/index.html)
~~~
1、下载安装包,部署UPMS服务器的任一目录,命令下载:
wget https://jaist.dl.sourceforge.net/project/openofficeorg.mirror/4.1.7/binaries/zh-CN/Apache_OpenOffice_4.1.7_Linux_x86-64_install-rpm_zh-CN.tar.gz
2、解压:tar -zxvf Apache_OpenOffice_4.1.7_Linux_x86-64_install-rpm_zh-CN.tar.gz
3、进入cd zh-CN/RPMS,安装必要的包,执行 yum localinstall *.rpm
4、再进入RPMS/desktop-integration目录,执行:rpm -ivh openoffice4.1.7-redhat-menus-4.1.7-9790.noarch.rpm
5、启动Openoffice服务:
cd /opt/openoffice4/program
soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard &
完成本地启动,如果需要远程访问,需要将host地址改成机器对应IP地址
6、查看服务是否启动(端口8100是否被soffice占用):netstat -lnp |grep 8100
显示结果:tcp 0 0 127.0.0.1:8100 0.0.0.0:* LISTEN 19501/soffice.bin
7、因为一般安装完后openoffice在转换pdf时候会因为缺失字体造成中文乱码情况,所以一般要将window下的字体库打包拷贝到linux服务器上。
(1) 查看系统字体文件cat /etc/fonts/fonts.conf
(2) 将window下的字符库上传到linux下。一般是在/usr/share/fonts目录下,创建fonts目录。
(3) 执行fc-cache。
(4) 重启openoffice。
~~~
*****
# 三、中文字体安装
如果需要预览的文档中包含中文字体,则需要在安装了openoffice软件的linux服务器上安装中文字体,安装过程如下:
~~~
1、使用fc-list查看服务器系统中已经安装的字体;如果没有该命令则可以根据实际情况使用如下命令安装:
在centos上,使用如下命令进行安装:
yum install -y fontconfig mkfontscale
在ubuntu上,使用如下命令进行安装:
sudo apt-get -y install fontconfig xfonts-utils
如果要查看系统中已经安装的中文字体,我们可以使用如下命令:
fc-list :lang=zh
2、上传Windows系统中的中文字体安装文件到服务器上的/usr/share/fonts/目录:
进入C:\Windows\Fonts目录,该目录下的所有的字体安装包都是可以上传到服务器的
选择一个或几个常用的中文字体安装包上传到服务器的/usr/share/fonts/目录
然后建立字体索引信息,更新字体缓存,使用如下命令:
cd /usr/share/fonts/
mkfontscale
mkfontdir
fc-cache
3、重启openoffice
使用kill命令杀死openoffice进程
执行上一章节的第5步骤
~~~
*****
# 四、项目中使用openoffice将文档转换为PDF预览
使用快开平台框架在项目中进行文档转换及预览时,需要文件先上传到minio文件服务中心,然后才能进行后续的转换及预览
## 4.1、修改upms配置
1. 进入nacos注册中心
2. 进入“配置管理/配置中心”菜单页面
3. 编辑sca-upms-biz的服务配置
4. 修改配置内容,示例说明如下:
```
#openoffice配置
jodconverter:
local:
enabled: false #是否启用openoffice
max-tasks-per-process: 10 #设置一个office进程在重启之前所能执行的最大任务数。默认为200个
port-numbers: 8100 #openoffice端口号
office-home: /opt/openoffice4/ #该属性是office的安装目录 .
```
更详细的配置说明可以前往该网址查看[jobconverter文档详解](https://blog.csdn.net/qingtian_1993/article/details/79901843)
5. 发布最新配置
6. 重启upms服务
*****
## 4.2、bootstrap页面使用预览功能示例
![](https://img.kancloud.cn/a0/59/a05947f8e10588726ef7482460f5244e_2160x1057.jpg)
```
function viewFile(filename,bucketName) {
var urlView = api + '/admin/sys-file/fileView/' + bucketName + '/' + filename
var windowUrl = window.URL || window.webkitURL;//处理浏览器兼容性
var xhr = new XMLHttpRequest();
xhr.open("GET", urlView, true);
xhr.responseType = "blob";
// xhr.setRequestHeader("Authorization", 'Bearer ' + session.get('token'),);
xhr.onload = function () {
if (this.status == 200) {
var blob = this.response;
var url="";
if (window.createObjectURL != undefined) { // basic
url = window.createObjectURL(blob);
} else if (window.webkitURL != undefined) { // webkit or chrome
try {
url = window.webkitURL.createObjectURL(blob);
} catch (error) {}
} else if (window.URL != undefined) { // mozilla(firefox)
try {
url = window.URL.createObjectURL(blob);
} catch (error) {}
}
window.open('/static/js/pdf/web/viewer.html?file='+encodeURIComponent(url))
}
}
xhr.send();
}
```
主要是访问`/admin/sys-file/fileView/ + bucketName + '/' + filename`后台请求地址,其中需要传递的那个参数分别是minio中的桶名称bucketName和需要预览的文件名称filename。
更完整的示例可以参看bootstrap前端框架下的`static\pages\sysadm\file`目录下的fileList.js文件
*****
## 4.3、vue页面使用预览功能示例
![页面示例](https://img.kancloud.cn/a0/6d/a06d76cf136e51fd4ef424466ca171e0_2149x680.jpg)
```
<script>
import { handleDown,previewPdf } from '@/util/util'
export default {
name: 'sys-file',
components:{uploadCard},
data() {
return {
}
},
created() {
},
mounted: function() {
},
computed: {
...mapGetters(['permissions']),
},
methods: {
viewPdf(row, index){
let type = matchType(row.fileName)
if (type === 'word' || type === 'excel' || type === 'ppt' || type === 'pdf' || type === 'txt'){
previewPdf(row.bucketName,row.fileName)
}else if (type === 'image' || type === 'video' || type === 'radio'){
this.$message.error('该文件暂不支持预览')
}else{
this.$message.error('该文件暂不支持预览')
}
},
}
}
</script>
```
调用`previewPdf`方法即可在浏览器中打开新的标签页进行文件预览,可以参考vue前端框架下的`src\views\admin\file`下的index.vue文件。
*****
## 4.4、在后台代码中集成openoffice
### 首先添加依赖
```
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.3.0</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.2</version>
</dependency>
<dependency>
<groupId>com.github.livesense</groupId>
<artifactId>jodconverter-core</artifactId>
<version>1.0.5</version>
</dependency>
```
### 添加配置
配置说明参考本文档`4.1、修改upms配置`章节
### 注入类
```
@Autowired(required = false)
private DocumentConverter converter;
```
### 使用示例
```
/**
* 文件转PDF预览
*
* @param bucket
* 桶名称
* @param fileName
* 文件空间/名称
* @param response
* @return
*/
@Inner(false)
@GetMapping("/fileView/{bucket}/{fileName}")
public void fileView(@PathVariable String bucket, @PathVariable String fileName, HttpServletResponse response) {
//获取文件并转换为input流
InputStream inputStream = sysFileService.getFile(bucket, fileName);
File targetFile = this.transfer(fileName, inputStream);
try {
if (targetFile != null) {
response.setContentType("application/pdf; charset=UTF-8");
IoUtil.copy(cn.hutool.core.io.IoUtil.toStream(targetFile), response.getOutputStream());
}
} catch (Exception e) {
log.error("文件转换异常: {}", e.getLocalizedMessage());
} finally {
cn.hutool.core.io.IoUtil.close(inputStream);
if (targetFile != null) {
//为了不占用服务器资源,故获取PDF文件流后,最后将临时文件删除
targetFile.deleteOnExit();
}
}
}
/*
* 将文件转换为PDF文档,根据需求可转换为其他类型
*/
private File transfer(String fileName, InputStream inputStream) {
File targetFile = null;
try {
targetFile = java.io.File.createTempFile(fileName.substring(0, fileName.lastIndexOf(".")), ".pdf");
// 文件转化
converter.convert(inputStream).to(targetFile).execute();
} catch (Exception e) {
log.error("文件读取异常: {}", e.getLocalizedMessage());
}
return targetFile;
}
```
网上可参考的集成示例:[SpringBoot2.x整合OpenOffice4](https://blog.csdn.net/li_jiazhi/article/details/105386337)、[SpringBoot集成jodconverter使用openoffice将word转为pdf](https://www.jianshu.com/p/77e0b6f5c7dd)
### 设置自定义转换PDF宽度
当excel宽度超过A4纸宽度后,需要实现如下代码,将PDF的宽度设置长,就可以避免excel转换为PDF时被默认截取
```
import org.jodconverter.core.DocumentConverter;
import org.jodconverter.core.document.DocumentFormatRegistry;
import org.jodconverter.core.office.OfficeManager;
import org.jodconverter.local.LocalConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Author xiangyu
* @Date 2021/3/19 17:13
* @Version 1.0
*/
@Configuration
public class JodConverterConfiguration {
@Bean
DocumentConverter localDocumentConverter(OfficeManager localOfficeManager, DocumentFormatRegistry documentFormatRegistry) {
return LocalConverter.builder().filterChain(
// new PageMarginsFilter(0,0,0,0), // 对word有用,对excel似乎没什么用
new JodConverterRefreshFilter(true) ).officeManager(localOfficeManager).formatRegistry(documentFormatRegistry).build();
}
}
```
```
import com.sun.star.awt.Size;
import com.sun.star.beans.PropertyValue;
import com.sun.star.lang.IllegalArgumentException;
import com.sun.star.lang.XComponent;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.view.PaperFormat;
import com.sun.star.view.XPrintable;
import org.jodconverter.core.office.OfficeContext;
import org.jodconverter.local.filter.FilterChain;
import org.jodconverter.local.filter.RefreshFilter;
/**
* @Author xiangyu
* @Date 2021/3/19 17:16
* @Version 1.0
*/
public class JodConverterRefreshFilter extends RefreshFilter {
public final static Size A6, A5, A4, A3, A2, A1, A0;
public final static Size B6, B5, B4, B3, B2, B1, B0;
static {
A6 = new Size(10500, 14800);
A5 = new Size(14800, 21000);
A4 = new Size(21000, 29700);
A3 = new Size(29700, 42000);
A2 = new Size(42000, 59400);
A1 = new Size(59400, 84100);
A0 = new Size(84100, 118900);
B6 = new Size(12500, 17600);
B5 = new Size(17600, 25000);
B4 = new Size(25000, 35300);
B3 = new Size(35300, 50000);
B2 = new Size(50000, 70700);
B1 = new Size(70700, 100000);
B0 = new Size(100000, 141400);
}
/**
* Creates a new refresh filter.
*/
public JodConverterRefreshFilter() {
this(false);
}
/**
* Creates a new refresh filter that will call or not the next filter in the chain according to
* the specified argument.
*
* @param lastFilter If {@code true}, then the filter won't call the next filter in the chain. If
* {@code false}, the next filter in the chain, if any, will be applied.
*/
public JodConverterRefreshFilter(final boolean lastFilter) {
super(lastFilter);
}
@Override
public void doFilter(
final OfficeContext context,
final XComponent document,
final FilterChain chain)
throws Exception {
setPaperInfo(document, new Size(67000, 20000));
super.doFilter(context, document, chain);
}
/**
* 设置纸张信息
* 请注意!!!PaperOrientation 和 PaperSize 不可以同时配置,否则有一个无效!
* <p>
* The default paper format and orientation is A4 and portrait.
*
* @param paperSize
*/
private void setPaperInfo(final XComponent document, final Size paperSize) throws IllegalArgumentException {
XPrintable xPrintable = UnoRuntime.queryInterface(XPrintable.class, document);
PropertyValue[] printerDesc = new PropertyValue[2];
// Paper Orientation(纵向横向)
// printerDesc[0] = new PropertyValue();
// printerDesc[0].Name = "PaperOrientation";
// printerDesc[0].Value = PaperOrientation.LANDSCAPE;
// Paper Format
printerDesc[0] = new PropertyValue();
printerDesc[0].Name = "PaperFormat";
printerDesc[0].Value = PaperFormat.USER;
// Paper Size
printerDesc[1] = new PropertyValue();
printerDesc[1].Name = "PaperSize";
printerDesc[1].Value = paperSize;
xPrintable.setPrinter(printerDesc);
}
}
```
- 服务组件
- sca-register注册配置中心
- sca-gateway服务网关
- sca-auth认证授权服务
- sca-upms权限管理服务
- sca-quartz定时任务服务
- sca-monitor系统监控服务
- sca-commservie通讯前置服务
- sca-sentinel限流熔断服务
- sca-codegen代码生成服务
- sca-message消息发送服务
- sca-rule规则引擎服务
- sca-workflow工作流引擎服务
- sca-report报表服务
- ELK日志服务
- SkyWalking链路跟踪
- Prometheus监控
- 技术组件
- sca-common-swagger(聚合文档)
- sca-common-log(系统日志)
- sca-common-sentinel(熔断限流)
- sca-common-feign(Feign接口调用)
- sca-common-sequence(分布式发号器)
- sca-common-gray(灰度发布)
- sca-common-security(授权认证)
- sca-common-datasource(动态数据源)
- sca-common-data(数据库及缓存)
- sca-common-oss(文件服务)
- sca-common-xss(XSS安全过滤)
- sca-common-test(微服务单元测试)
- sca-common-test-alone(单体应用单元测试)
- sca-common-memdb(内存数据库)
- 日志脱敏
- Pdf文档转换及预览
- IDE组件
- IDE技术组件介绍
- FastJson技术组件类
- 对象转string技术组件
- JDBC操作技术组件类
- SQL查询(完整SQL)技术组件
- 关闭连接技术组件
- 执行预编译SQL(update)技术组件
- 数据分页查询技术组件
- 数据删除技术组件
- 数据批量插入技术组件
- 数据插入技术组件
- 数据更新技术组件
- 标准数据查询方法(单表)技术组件
- 获取序列号技术组件
- 行数统计技术组件
- 调用存储过程技术组件
- 预编译SQL查询(参数)
- 集合操作技术组件类
- Set和List类型互转技术组件
- 交集技术组件
- 增加元素(批量)技术组件
- 增加元素技术组件
- 差集技术组件
- 并集技术组件
- 替换元素技术组件
- 集合删除(下标)技术组件
- 集合删除(元素)技术组件
- 集合清空技术组件
- 金额处理技术组件类
- 乘技术组件
- 元转换为分技术组件
- 减技术组件
- 删除千分符技术组件
- 加技术组件
- 取金额绝对值技术组件
- 字符串转BigDecimal技术组件
- 是否为0技术组件
- 金额格式化技术组件
- 金额比较技术组件
- 金额舍入技术组件
- 金额转大写技术组件
- 除技术组件
- Redishash操作的组件集合
- 删除字段技术组件
- 字段是否存在技术组件
- 设置字段值(覆盖)技术组件
- 获取字段值技术组件
- 设置字段值(不覆盖)技术组件
- 批量设置字段值技术组件
- 批量获取字段值技术组件
- 获取字段数量技术组件
- 获取字段名称列表技术组件
- 获取字段值列表技术组件
- 获取字段和值列表技术组件
- Redis_Key操作技术组件类
- 获得redisTemplate技术组件
- 重命名key技术组件
- 清空Redis技术组件
- key是否存在技术组件
- 取消过期时间技术组件
- 获取数据结构类型技术组件
- 设置过期时间(毫秒)技术组件
- 设置固定过期时间技术组件
- 剩余存活时间(秒)技术组件
- 删除(批量)技术组件
- 删除(单个)技术组件
- 移动key到指定db技术组件
- 集合排序(正序)技术组件
- Redis_List操作组件操作类
- 插入(尾部)技术组件
- 插入(头部)技术组件
- 列表长度技术组件
- 截取区间列表元素技术组件
- 保留列表元素技术组件
- 获取列表元素(按下标)技术组件
- 设置列表元素(按下标)技术组件
- 删除元素(按值出现次数)技术组件
- 移除并返回元素(头部)技术组件
- 移除并返回元素(尾部)技术组件
- 已有列表插入(尾部)技术组件
- 已有列表插入(头部)技术组件
- 已有列表插入(按位置)技术组件
- 配置中心技术组件类
- 获取Nacos配置内容技术组件
- 通讯前置技术组件类
- 异步应答技术组件
- 组报文(前置)技术组件
- 解报文(前置)技术组件
- 调用第三方交易技术组件
- 调试输出技术组件类
- 输出日志(debug)技术组件
- 输出日志(warn)技术组件
- 输出日志(error)技术组件
- 输出日志(info)技术组件
- 编解码处理技术组件类
- BCD编码技术组件
- BCD解码技术组件
- Base64编码技术组件
- Base64解码技术组件
- 服务调用技术组件类
- 交易调用(分布式)技术组件
- 交易调用(第三方系统)技术组件
- 服务调用(rest服务名)技术组件
- 服务调用(ip-port)技术组件
- 日期时间技术组件类
- 当前时间(date)技术组件
- 当前时间(字符串)技术组件
- 当前时间(毫秒)技术组件
- 日期格式检查技术组件
- 日期比较技术组件
- 日期相加技术组件
- 格式化日期技术组件
- 获取日历字段技术组件
- 计算时间差(Date)技术组件
- 计算时间差(字符串)技术组件
- 转换日期对象技术组件
- 文件操作技术组件类
- MD5计算签名技术组件
- ZIP文件压缩技术组件
- ZIP文件解压缩技术组件
- 写文件内容技术组件
- 创建文件技术组件
- 创建文件目录技术组件
- 文件删除技术组件
- 文件合并技术组件
- 文件大小技术组件
- 文件存在检查技术组件
- 文件拷贝技术组件
- 文件查找技术组件
- 读文件内容技术组件
- 读文件行技术组件
- 数据库操作技术组件类
- 切换数据源技术组件
- 删除(BatchIds)技术组件
- 删除(Entity)技术组件
- 删除(ID)技术组件
- 删除(columnMap)技术组件
- 回滚上一事务技术组件
- 回滚全部事务技术组件
- 开启事务技术组件
- 执行指定方法技术组件
- 提交上一事务技术组件
- 提交全部事务技术组件
- 新增数据技术组件
- 更新(Entity)技术组件
- 更新(ID)技术组件
- 查询(BatchIds)技术组件
- 查询(ID)技术组件
- 查询(Objects)技术组件
- 查询(columnMap)技术组件
- 查询(list)技术组件
- 查询(map)技术组件
- 查询(分页)技术组件
- 查询(单条)技术组件
- 查询(总条数)技术组件
- 清理数据源技术组件
- 数据字典技术组件类
- 平台字典技术组件
- 应用字典技术组件
- 银行字典技术组件
- 平台内置组件技术组件类
- switch选择器技术组件
- 从异步组件中获取数据技术组件
- 初始化线程池技术组件
- 判断异步组件是否已完成技术组件
- 当期线程休眠技术组件
- 获取异常信息到容器技术组件
- 获取环境变量技术组件
- 获取系统变量技术组件
- 表达式判断技术组件
- 设置全局错误技术组件
- 随机正整数技术组件
- 对象操作技术组件类
- map转对象技术组件
- 创建list技术组件
- 创建实体类对象(空对象)技术组件
- 创建实体对象(赋值)技术组件
- 反序列化对象技术组件
- 对象属性赋值技术组件
- 对象序列化成数组技术组件
- 获取对象类型名称技术组件
- 获得对象字段值技术组件
- 获得对象属性及值列表技术组件
- Redis_Set操作技术组件类
- 添加元素技术组件
- 获取所有元素技术组件
- 移除指定元素技术组件
- 随机移除并返回(一个)技术组件
- 随机移除并返回(多个)技术组件
- 集合元素数量技术组件
- 是否包含指定元素技术组件
- 随机返回元素(一个)技术组件
- 随机返回元素(多个)技术组件
- Redis_String操作技术组件类
- 设置值(覆盖)技术组件
- 获取值技术组件
- 获取值(批量)技术组件
- 字符串追加值技术组件
- 设置值(不覆盖)技术组件
- 设置值(带过期时间:秒)技术组件
- 覆盖部分值技术组件
- 截取区间字符串技术组件
- 赋值并返回旧值技术组件
- 值长度技术组件
- Redis_ZSet操作技术组件类
- ZSet添加元素技术组件
- 获取区间集合元素(正序按下标)技术组件
- 获取区间集合元素(倒序按下标)技术组件
- 移除集合元素技术组件
- 增加元素的排序值技术组件
- 获取元素排名(正序)技术组件
- 获取元素排名(倒序)技术组件
- ZSet集合元素数量技术组件
- 获取元素排序值技术组件
- 统计区间元素数量技术组件
- 移除区间元素(按排名)技术组件
- 移除区间元素(按排序值)技术组件
- 容器操作技术组件类
- 取容器深度技术组件
- 容器删除(按value)技术组件
- 容器变量删除(保留keys)技术组件
- 容器变量删除(删除单个key)技术组件
- 容器变量删除(删除多个key)技术组件
- 容器变量赋值技术组件
- 容器变量赋值(批量)技术组件
- 获取容器变量值技术组件
- 容器变量拷贝技术组件
- 容器变量获取(批量)技术组件
- 容器清空技术组件
- 容器多层次赋值技术组件
- Redis计算操作组件类
- 减(整数)技术组件
- 减1技术组件
- 加(整数)技术组件
- 加1技术组件
- 加(浮点数)技术组件
- hash字段加(整数)技术组件
- UUID和ID技术组件类
- 生成UUID技术组件
- 生成ID技术组件
- 批量生成ID技术组件
- 公共方法源码
- 安全组件技术组件类
- 3DES加密技术组件
- 3DES解密技术组件
- DES加密技术组件
- DES解密技术组件
- MD5十进制字符串技术组件
- MD5计算签名技术组件
- 获取CRC16码技术组件
- excel技术组件类
- 获取工作簿技术组件
- 获取工作簿(文件名)技术组件
- 工作簿写文件技术组件
- sheet数技术组件
- sheet行数技术组件
- 工作簿数据行数技术组件
- sheet列表技术组件
- 获取sheet技术组件
- 创建工作簿(xlsx)技术组件
- 创建工作簿(指定格式)技术组件
- 工作簿64编码技术组件
- 文件是否超出限制技术组件
- 文件是否超出限制(文件名)技术组件
- 输出文件地址技术组件
- 新建日期文件夹技术组件
- 截取文件路径技术组件
- 工作簿清理技术组件
- 打开Excel文件技术组件
- 取Excel列数据技术组件
- 取Excel单元格技术组件
- 取Excel行列数技术组件
- 取Excel行数据技术组件
- 公共方法
- 字符串技术组件类
- 字符串切割技术组件
- 字符串去空格技术组件
- 字符串是否包含技术组件
- 字符串截取技术组件
- 统计字符数技术组件
- 统计字节数技术组件
- 以子字符串开始技术组件
- 以子字符串结尾技术组件
- 字符串转大写技术组件
- 字符串转小写技术组件
- 是否包含全角字符技术组件
- 字符串拼接技术组件
- 字符串连接技术组件
- 字符串替换技术组件
- 字符串正则表达式替换技术组件
- 字符串非空技术组件
- 字符串补齐技术组件
- 正则表达式匹配技术组件
- 字符串编码转换技术组件
- 字符串查找定位技术组件
- 变量操作技术组件类
- 字段检查(长度范围)技术组件
- 正则表达式检查技术组件
- 数字检查(大小区间)技术组件
- 变量字段检查(类型、长度)技术组件
- 身份证号校验技术组件
- 身份照15位转18位技术组件
- 上传下载技术组件类
- FTP文件上传技术组件
- FTP文件下载技术组件
- SFTP文件上传技术组件
- SFTP文件下载技术组件
- 自定义组件开发
- IDE技术组件包,技术组件类创建
- 新建、编辑IDE技术组件
- 过时组件介绍
- 技术组件API
- 新建普通java类
- 注册技术组件
- 打包技术组件
- 前端控件