├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── LICENSE ├── README.md ├── kbase-doc-alpha ├── lib │ ├── jacob.jar │ └── jodconverter-core-3.0-beta-4.jar ├── pom.xml └── src │ ├── main │ ├── java │ │ ├── com │ │ │ └── eastrobot │ │ │ │ └── doc │ │ │ │ ├── KbaseDocAlphaApplication.java │ │ │ │ ├── config │ │ │ │ ├── BaseController.java │ │ │ │ ├── KbsServletContextListener.java │ │ │ │ ├── OpenOffice.java │ │ │ │ ├── Swagger2.java │ │ │ │ ├── SwaggerInterceptor.java │ │ │ │ ├── SystemConstants.java │ │ │ │ ├── WebMvcConfig.java │ │ │ │ └── WebappContext.java │ │ │ │ ├── dao │ │ │ │ └── AttachmentRepository.java │ │ │ │ ├── model │ │ │ │ └── entity │ │ │ │ │ └── Attachment.java │ │ │ │ ├── service │ │ │ │ ├── ConvertService.java │ │ │ │ ├── FileService.java │ │ │ │ ├── WatermarkService.java │ │ │ │ └── impl │ │ │ │ │ ├── ConvertServiceImpl.java │ │ │ │ │ ├── FileServiceImpl.java │ │ │ │ │ └── WatermarkServiceImpl.java │ │ │ │ ├── util │ │ │ │ ├── FileExtensionUtils.java │ │ │ │ ├── HtmlUtils.java │ │ │ │ ├── MammothUtils.java │ │ │ │ ├── OpenOfficeUtils.java │ │ │ │ └── POIUtils.java │ │ │ │ ├── watermark │ │ │ │ ├── AbstractProcessor.java │ │ │ │ ├── ExcelProcessor.java │ │ │ │ ├── FontImage.java │ │ │ │ ├── ImageProcessor.java │ │ │ │ ├── PdfProcessor.java │ │ │ │ ├── PowerPointProcessor.java │ │ │ │ ├── WatermarkException.java │ │ │ │ ├── WatermarkProcessor.java │ │ │ │ └── WordProcessor.java │ │ │ │ └── web │ │ │ │ └── controller │ │ │ │ ├── IndexController.java │ │ │ │ └── WatermarkController.java │ │ └── org │ │ │ └── artofsolving │ │ │ └── jodconverter │ │ │ └── document │ │ │ └── DefaultDocumentFormatRegistry.java │ └── resources │ │ ├── application.properties │ │ ├── static │ │ ├── DATAS │ │ │ └── README.txt │ │ ├── css │ │ │ ├── contents.css │ │ │ ├── pastefromword.css │ │ │ └── style.css │ │ ├── img │ │ │ ├── edit.png │ │ │ ├── list.png │ │ │ ├── read.png │ │ │ └── upload.png │ │ └── js │ │ │ ├── edit.js │ │ │ ├── index.js │ │ │ ├── template-web.js │ │ │ └── upload.js │ │ └── templates │ │ ├── body.html │ │ ├── edit.html │ │ ├── index.html │ │ ├── script.html │ │ └── upload.html │ └── test │ └── java │ └── com │ └── eastrobot │ └── doc │ ├── KbaseDocApplicationTests.java │ ├── dao │ └── AttachmentRepositoryTests.java │ ├── demo │ └── Tests.java │ ├── samples │ ├── BackgroundImage.java │ ├── WatermarkExcelPicture.java │ ├── WatermarkExcelTests.java │ ├── WatermarkPdfTests.java │ ├── WatermarkPicture.java │ ├── WatermarkPptTests.java │ └── WatermarkWordTests.java │ ├── util │ ├── AddDimensionedImage.java │ ├── BaseTests.java │ ├── ConvertTests.java │ ├── FormFieldTests.java │ ├── HtmlUtilsTests.java │ └── PdfToHtmlTests.java │ ├── watermark │ ├── ExcelProcessorTests.java │ ├── FontImageTests.java │ ├── ImageProcessorTests.java │ ├── PdfProcessorTests.java │ ├── PowerPointProcessorTests.java │ ├── WatermarkProcessorTests.java │ └── WordProcessorTests.java │ └── web │ └── controller │ └── IndexControllerTests.java ├── kbase-doc-beta ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── ibothub │ │ │ └── doc │ │ │ ├── KbaseDocBetaApplication.java │ │ │ ├── config │ │ │ ├── SwaggerConfig.java │ │ │ └── SystemConstants.java │ │ │ ├── dao │ │ │ └── AttachmentRepository.java │ │ │ ├── entity │ │ │ └── Attachment.java │ │ │ ├── service │ │ │ ├── AttachmentService.java │ │ │ └── impl │ │ │ │ └── AttachmentServiceImpl.java │ │ │ ├── util │ │ │ └── FileExtensionUtils.java │ │ │ └── web │ │ │ └── controller │ │ │ └── IndexController.java │ └── resources │ │ ├── application.properties │ │ └── static │ │ └── DATAS │ │ └── README.txt │ └── test │ └── java │ └── com │ └── ibothub │ └── doc │ └── service │ └── ConverterTests.java ├── mvnw ├── mvnw.cmd └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | 18 | ### NetBeans ### 19 | nbproject/private/ 20 | build/ 21 | nbbuild/ 22 | dist/ 23 | nbdist/ 24 | .nb-gradle/ 25 | ibothub.db 26 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekoz/kbase-doc/33995dc4dc79d434ebb58255d997c27b5d014492/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 文档在线预览编辑系统 2 | 3 | [![Badge](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu/#/zh_CN) 4 | 5 | > 之前做过在线编辑文档的功能,使用 [webdav](https://www.webdavsystem.com/) 来实现在线编辑, 6 | 存在的问题是编辑页面保存不可控(是否可以保存为版本、是否可以放弃保存等)。如果大家有实现类似功能,希望能提供帮助。 7 | 8 | > 当前应用的主要功能是采用 LibreOffice 和 ckeditor 来实现文档的预览和编辑功能,先介绍操作步骤,再谈下面临的问题。 9 | 10 | ### 操作步骤 11 | 12 | #### 文件列表 13 | 展示当前用户已上传的文件,并提供预览和删除操作 14 | 15 | ![列表页面](kbase-doc-alpha/src/main/resources/static/img/list.png?raw=true "列表页面") 16 | 17 | #### 上传文件 18 | 上传文件时直接利用 [LibreOffice](https://www.libreoffice.org/) 将文件转换成 html并保存 19 | 20 | ![上传页面](kbase-doc-alpha/src/main/resources/static/img/upload.png?raw=true "上传页面") 21 | 22 | #### 预览文件 23 | 用户可以在预览界面单击编辑按钮,并实现保存或保存为版本功能 24 | 25 | ![预览页面](kbase-doc-alpha/src/main/resources/static/img/read.png?raw=true "预览页面") 26 | 27 | ![编辑页面](kbase-doc-alpha/src/main/resources/static/img/edit.png?raw=true "编辑页面") 28 | 29 | ### 已知问题 30 | 1. word中包含图片如何处理?目前是用Html正则将图片加上一个 地址 进行加载,这样在保存的时候,html文件的图片地址有异常 31 | 32 | 答:word 中的图片,不在后端进行处理,如果该图片是网络图片,可以进行正常访问吗,如果该图片是本地图片,前端采用js处理 33 | 34 | 2. html 图片的正则未区分网络图片还是本地图片 35 | 36 | 答:见第1点 37 | 38 | 3. 用户修改word中的图片如何处理? 39 | 40 | 答:按照第1点处理后,不存在该问题 41 | 42 | 4. 将html转换成doc后,文件内容格式有误 43 | 44 | 答:html直接转换成docx,采用 LibreOffice 转换,效果略优于 OpenOffice 45 | 46 | 5. windows 操作系统上如何删除一个正在被占用的进程? 47 | 6. 是否能很好的兼容 excel 和 ppt 的预览编辑功能 48 | 49 | 答:暂时不能 50 | 51 | 7. Cannot read JPEG2000 image: Java Advanced Imaging (JAI) Image I/O Tools are not installed 52 | ``` 53 | 54 | com.github.jai-imageio 55 | jai-imageio-core 56 | 1.4.0 57 | 58 | 59 | com.github.jai-imageio 60 | jai-imageio-jpeg2000 61 | 1.3.0 62 | 63 | ``` 64 | 65 | ### 总结 66 | 1. visio 文件可采用 LibreOffice 转换成 pdf 实现在线预览,OpenOffice无法实现 67 | 2. LibreOffice 支持转换加密的 office 文件,前提是给出明文密码。详见 [ConvertTests#testEncrypt](kbase-doc-alpha/src/test/java/com/eastrobot/doc/util/ConvertTests.java) 68 | 3. pdf 文件可以调用 pdf2dom 来实现转换 html,从而也可以在线编辑。详见 [PdfToHtmlTests#pdf2html](kbase-doc-alpha/src/test/java/com/eastrobot/doc/util/PdfToHtmlTests.java) 69 | 4. 水印(Watermark)实现方案,本案例中实现了对图片,word,excel,ppt,pdf等格式的水印处理,支持文本水印和图片水印。详见 [WatermarkProcessorTests](kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/WatermarkProcessorTests.java) 70 | 71 | ### Restful Apis 72 | [http://localhost:8080/kbase-doc/swagger-ui.html](http://localhost:8080/kbase-doc/swagger-ui.html) 73 | 74 | ### 感谢 75 | [mirkonasato / jodconverter](https://github.com/mirkonasato/jodconverter) 76 | 77 | [sbraconnier/jodconverter](https://github.com/sbraconnier/jodconverter) 78 | -------------------------------------------------------------------------------- /kbase-doc-alpha/lib/jacob.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekoz/kbase-doc/33995dc4dc79d434ebb58255d997c27b5d014492/kbase-doc-alpha/lib/jacob.jar -------------------------------------------------------------------------------- /kbase-doc-alpha/lib/jodconverter-core-3.0-beta-4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekoz/kbase-doc/33995dc4dc79d434ebb58255d997c27b5d014492/kbase-doc-alpha/lib/jodconverter-core-3.0-beta-4.jar -------------------------------------------------------------------------------- /kbase-doc-alpha/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | kbase-doc 7 | com.eastrobot 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | kbase-doc-alpha 13 | 14 | 15 | 16 | org.apache.poi 17 | poi-ooxml 18 | ${poi.version} 19 | 20 | 21 | org.apache.poi 22 | poi-scratchpad 23 | ${poi.version} 24 | 25 | 26 | fr.opensagres.xdocreport 27 | org.apache.poi.xwpf.converter.xhtml 28 | 1.0.6 29 | 30 | 31 | org.zwobble.mammoth 32 | mammoth 33 | 0.0.4 34 | 35 | 36 | 37 | org.artofsolving.jodconverter 38 | jodconverter-core 39 | 3.0-beta-4 40 | system 41 | ${project.basedir}/lib/jodconverter-core-3.0-beta-4.jar 42 | 43 | 44 | commons-cli 45 | commons-cli 46 | 1.2 47 | 48 | 49 | org.openoffice 50 | juh 51 | 4.1.2 52 | 53 | 54 | org.openoffice 55 | unoil 56 | 4.1.2 57 | 58 | 59 | 60 | 61 | com.googlecode.juniversalchardet 62 | juniversalchardet 63 | 1.0.3 64 | 65 | 66 | 67 | org.apache.httpcomponents 68 | httpclient 69 | 70 | 71 | org.apache.httpcomponents 72 | httpmime 73 | 74 | 75 | 76 | io.springfox 77 | springfox-swagger2 78 | ${swagger.version} 79 | 80 | 81 | 82 | io.springfox 83 | springfox-swagger-ui 84 | ${swagger.version} 85 | 86 | 87 | 88 | net.sf.cssbox 89 | pdf2dom 90 | 1.7 91 | 92 | 93 | 94 | com.itextpdf 95 | itextpdf 96 | 5.5.13.3 97 | 98 | 99 | 100 | org.docx4j 101 | docx4j 102 | 3.3.3 103 | 104 | 105 | log4j 106 | log4j 107 | 108 | 109 | slf4j-log4j12 110 | org.slf4j 111 | 112 | 113 | 114 | 115 | 116 | com.github.jai-imageio 117 | jai-imageio-core 118 | 1.4.0 119 | 120 | 121 | com.github.jai-imageio 122 | jai-imageio-jpeg2000 123 | 1.3.0 124 | 125 | 126 | 127 | 128 | org.springframework.boot 129 | spring-boot-devtools 130 | runtime 131 | 132 | 133 | org.projectlombok 134 | lombok 135 | true 136 | 137 | 138 | org.springframework.boot 139 | spring-boot-starter-test 140 | test 141 | 142 | 143 | org.springframework.restdocs 144 | spring-restdocs-mockmvc 145 | test 146 | 147 | 148 | 149 | 150 | 151 | 152 | org.springframework.boot 153 | spring-boot-maven-plugin 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/KbaseDocAlphaApplication.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableAsync; 6 | 7 | /** 8 | * @author eko.zhan 9 | */ 10 | @SpringBootApplication 11 | @EnableAsync 12 | public class KbaseDocAlphaApplication { 13 | 14 | public static void main(String[] args) { 15 | SpringApplication.run(KbaseDocAlphaApplication.class, args); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/BaseController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import java.io.File; 7 | 8 | import javax.servlet.ServletContext; 9 | 10 | import org.apache.commons.io.FilenameUtils; 11 | import org.artofsolving.jodconverter.OfficeDocumentConverter; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.http.MediaType; 14 | 15 | import lombok.extern.slf4j.Slf4j; 16 | 17 | 18 | /** 19 | * @author eko.zhan 20 | * @date 2018年9月2日 下午2:12:10 21 | * @version 1.0 22 | */ 23 | @Slf4j 24 | public class BaseController { 25 | 26 | @Autowired 27 | protected ServletContext servletContext; 28 | 29 | /** 30 | * 转换文件 31 | * @author eko.zhan at 2018年9月2日 下午2:16:14 32 | * @param originFile 33 | * @param targetFile 34 | */ 35 | protected void convert(File originFile, File targetFile) { 36 | WebappContext webappContext = WebappContext.get(servletContext); 37 | OfficeDocumentConverter converter = webappContext.getDocumentConverter(); 38 | try { 39 | long startTime = System.currentTimeMillis(); 40 | converter.convert(originFile, targetFile); 41 | long conversionTime = System.currentTimeMillis() - startTime; 42 | log.info(String.format("successful conversion: %s [%db] to %s in %dms", FilenameUtils.getExtension(originFile.getName()), originFile.length(), FilenameUtils.getExtension(targetFile.getName()), conversionTime)); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | log.error(String.format("failed conversion: %s [%db] to %s; %s; input file: %s", FilenameUtils.getExtension(originFile.getName()), originFile.length(), FilenameUtils.getExtension(targetFile.getName()), e, targetFile.getName())); 46 | } 47 | } 48 | 49 | /** 50 | * 根据指定的文件名称获取文件类型 51 | * @author eko.zhan at 2018年9月2日 下午3:12:57 52 | * @param filename 53 | * @return 54 | */ 55 | protected MediaType getMediaType(String filename) { 56 | // application/pdf 57 | // application/xml 58 | // image/gif, ... 59 | String mineType = servletContext.getMimeType(filename); 60 | try { 61 | MediaType mediaType = MediaType.parseMediaType(mineType); 62 | return mediaType; 63 | } catch (Exception e) { 64 | return MediaType.APPLICATION_OCTET_STREAM; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/KbsServletContextListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import javax.servlet.ServletContextEvent; 7 | import javax.servlet.ServletContextListener; 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.context.annotation.Configuration; 11 | 12 | /** 13 | * @author eko.zhan 14 | * @date 2017年8月8日 下午8:32:46 15 | * @version 1.0 16 | */ 17 | @Configuration 18 | public class KbsServletContextListener implements ServletContextListener { 19 | 20 | @Autowired 21 | private OpenOffice openOffice; 22 | 23 | @Override 24 | public void contextInitialized(ServletContextEvent event) { 25 | WebappContext.init(event.getServletContext(), openOffice); 26 | } 27 | 28 | @Override 29 | public void contextDestroyed(ServletContextEvent event) { 30 | WebappContext.destroy(event.getServletContext()); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/OpenOffice.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.stereotype.Component; 11 | 12 | /** 13 | * @author eko.zhan 14 | * @date 2017年8月9日 上午9:30:15 15 | * @version 1.0 16 | */ 17 | @Component 18 | @Getter 19 | @Setter 20 | public class OpenOffice { 21 | 22 | @Value("${office.port}") 23 | private String port; 24 | @Value("${office.home}") 25 | private String home; 26 | @Value("${office.profile}") 27 | private String profile; 28 | @Value("${office.fileSizeMax}") 29 | private String fileSizeMax; 30 | 31 | } 32 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/Swagger2.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | import springfox.documentation.builders.ApiInfoBuilder; 10 | import springfox.documentation.builders.PathSelectors; 11 | import springfox.documentation.builders.RequestHandlerSelectors; 12 | import springfox.documentation.service.*; 13 | import springfox.documentation.spi.DocumentationType; 14 | import springfox.documentation.spi.service.contexts.SecurityContext; 15 | import springfox.documentation.spring.web.plugins.Docket; 16 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 17 | 18 | import java.util.List; 19 | 20 | import static com.google.common.collect.Lists.newArrayList; 21 | 22 | /** 23 | * @author eko.zhan 24 | * @date 2017年12月2日 上午11:39:23 25 | * @version 1.0 26 | */ 27 | @Configuration 28 | @EnableSwagger2 29 | public class Swagger2 { 30 | 31 | @Bean 32 | public Docket createRestApi() { 33 | return new Docket(DocumentationType.SWAGGER_2) 34 | .apiInfo(apiInfo()) 35 | .securitySchemes(securitySchemes()) 36 | .securityContexts(securityContexts()) 37 | .select() 38 | .apis(RequestHandlerSelectors.basePackage("com.eastrobot.doc.web")) 39 | .paths(PathSelectors.any()) 40 | .build(); 41 | } 42 | 43 | private List securitySchemes() { 44 | return newArrayList(new ApiKey(SystemConstants.API_KEY, SystemConstants.API_TOKEN, SystemConstants.API_PASSAS)); 45 | } 46 | 47 | private List securityContexts() { 48 | return newArrayList( 49 | SecurityContext.builder() 50 | .securityReferences(defaultAuth()) 51 | .forPaths(PathSelectors.any()) 52 | .build() 53 | ); 54 | } 55 | 56 | private List defaultAuth() { 57 | AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); 58 | AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; 59 | authorizationScopes[0] = authorizationScope; 60 | return newArrayList(new SecurityReference(SystemConstants.API_KEY, authorizationScopes)); 61 | } 62 | 63 | private ApiInfo apiInfo() { 64 | return new ApiInfoBuilder() 65 | .title("Spring Boot 中使用 Swagger2 构建 RESTful APIs ") 66 | .description("") 67 | .termsOfServiceUrl("http://ekozhan.com/kbase-doc/") 68 | .contact(new Contact("ekozhan", "http://ekozhan.com/", "eko.z@outlook.com")) 69 | .version("1.0") 70 | .build(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/SwaggerInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import org.apache.commons.lang3.StringUtils; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.stereotype.Component; 10 | import org.springframework.web.servlet.HandlerInterceptor; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.util.Objects; 16 | 17 | /** 18 | * @author eko.zhan 19 | * @version 1.0 20 | * @date 2019/3/12 10:25 21 | */ 22 | @Component 23 | public class SwaggerInterceptor implements HandlerInterceptor { 24 | 25 | @Value("${api.token}") 26 | private String token; 27 | 28 | @Override 29 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 30 | String requestURI = request.getRequestURI(); 31 | if (!StringUtils.isEmpty(requestURI)) { 32 | String apiToken = request.getHeader(SystemConstants.API_TOKEN); 33 | if (StringUtils.isEmpty(apiToken) || !Objects.equals(token, apiToken)) { 34 | response.setStatus(HttpStatus.UNAUTHORIZED.value()); 35 | return false; 36 | } 37 | } 38 | return true; 39 | } 40 | 41 | @Override 42 | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 43 | 44 | } 45 | 46 | @Override 47 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/SystemConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import com.google.common.collect.Maps; 7 | 8 | import java.util.Map; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @date 2017年12月6日 下午4:26:58 13 | * @version 1.0 14 | */ 15 | public class SystemConstants { 16 | 17 | public static String HTML_HEADER = ""; 18 | 19 | public static String HTML_FOOTER = ""; 20 | 21 | public final static String API_KEY = "apiKey"; 22 | public final static String API_TOKEN = "apiToken"; 23 | public final static String API_PASSAS = "header"; 24 | 25 | /** 26 | * 目标文件后缀 27 | */ 28 | public final static String OUTPUT_EXTENSION = "html"; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/WebMvcConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.core.Ordered; 8 | import org.springframework.web.servlet.config.annotation.*; 9 | 10 | import javax.annotation.Resource; 11 | 12 | /** 13 | * @author eko.zhan 14 | * @date 2017年7月29日 上午9:26:27 15 | * @version 1.0 16 | */ 17 | @Configuration 18 | public class WebMvcConfig implements WebMvcConfigurer { 19 | 20 | @Resource 21 | private SwaggerInterceptor swaggerInterceptor; 22 | 23 | @Override 24 | public void addViewControllers(ViewControllerRegistry registry) { 25 | registry.addViewController( "/" ).setViewName("index"); 26 | registry.setOrder(Ordered.HIGHEST_PRECEDENCE ); 27 | 28 | registry.addViewController( "/edit" ).setViewName("edit"); 29 | registry.addViewController( "/upload" ).setViewName("upload"); 30 | } 31 | 32 | @Override 33 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 34 | registry.addResourceHandler("swagger-ui.html") 35 | .addResourceLocations("classpath:/META-INF/resources/"); 36 | registry.addResourceHandler("/webjars*") 37 | .addResourceLocations("classpath:/META-INF/resources/webjars/"); 38 | } 39 | 40 | @Override 41 | public void addInterceptors(InterceptorRegistry registry) { 42 | registry.addInterceptor(swaggerInterceptor).addPathPatterns("/watermark/**"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/config/WebappContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.config; 5 | 6 | import java.io.File; 7 | 8 | import javax.servlet.ServletContext; 9 | 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory; 12 | import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload; 13 | import org.artofsolving.jodconverter.OfficeDocumentConverter; 14 | import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration; 15 | import org.artofsolving.jodconverter.office.OfficeManager; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | /** 20 | * @author eko.zhan 21 | * @date 2017年8月8日 下午8:50:28 22 | * @version 1.0 23 | */ 24 | public class WebappContext { 25 | 26 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 27 | 28 | private static final String KEY = WebappContext.class.getName(); 29 | 30 | private final ServletFileUpload fileUpload; 31 | 32 | private final OfficeManager officeManager; 33 | private final OfficeDocumentConverter documentConverter; 34 | 35 | public WebappContext(ServletContext servletContext, OpenOffice openOffice) { 36 | DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(); 37 | fileUpload = new ServletFileUpload(fileItemFactory); 38 | if (openOffice.getFileSizeMax() != null) { 39 | fileUpload.setFileSizeMax(Integer.parseInt(openOffice.getFileSizeMax())); 40 | logger.info("max file upload size set to " + openOffice.getFileSizeMax()); 41 | } else { 42 | logger.warn("max file upload size not set"); 43 | } 44 | 45 | DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); 46 | if (openOffice.getPort() != null) { 47 | String ports = openOffice.getPort(); 48 | String[] portArr = ports.split(","); 49 | int[] portArrInt = new int[portArr.length]; 50 | int i = 0; 51 | for (String port : portArr){ 52 | portArrInt[i++] = Integer.parseInt(port); 53 | } 54 | configuration.setPortNumbers(portArrInt); 55 | } 56 | if (openOffice.getHome() != null) { 57 | configuration.setOfficeHome(new File(openOffice.getHome())); 58 | } 59 | if (StringUtils.isNotBlank(openOffice.getProfile())) { 60 | configuration.setTemplateProfileDir(new File(openOffice.getProfile())); 61 | } 62 | 63 | officeManager = configuration.buildOfficeManager(); 64 | documentConverter = new OfficeDocumentConverter(officeManager); 65 | } 66 | 67 | protected static void init(ServletContext servletContext, OpenOffice openOffice) { 68 | WebappContext instance = new WebappContext(servletContext, openOffice); 69 | servletContext.setAttribute(KEY, instance); 70 | instance.officeManager.start(); 71 | } 72 | 73 | protected static void destroy(ServletContext servletContext) { 74 | WebappContext instance = get(servletContext); 75 | instance.officeManager.stop(); 76 | } 77 | 78 | public static WebappContext get(ServletContext servletContext) { 79 | return (WebappContext) servletContext.getAttribute(KEY); 80 | } 81 | 82 | public ServletFileUpload getFileUpload() { 83 | return fileUpload; 84 | } 85 | 86 | public OfficeManager getOfficeManager() { 87 | return officeManager; 88 | } 89 | 90 | public OfficeDocumentConverter getDocumentConverter() { 91 | return documentConverter; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/dao/AttachmentRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.eastrobot.doc.dao; 5 | 6 | import com.eastrobot.doc.model.entity.Attachment; 7 | import org.springframework.data.repository.CrudRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @version v1.0 13 | * @date 2022/10/18 21:00 14 | */ 15 | @Repository 16 | public interface AttachmentRepository extends CrudRepository { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/model/entity/Attachment.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc.model.entity; 2 | 3 | import java.time.LocalDateTime; 4 | import javax.persistence.Entity; 5 | import javax.persistence.GeneratedValue; 6 | import javax.persistence.GenerationType; 7 | import javax.persistence.Id; 8 | import javax.persistence.Table; 9 | import javax.persistence.Transient; 10 | import lombok.AllArgsConstructor; 11 | import lombok.Builder; 12 | import lombok.Data; 13 | import lombok.NoArgsConstructor; 14 | 15 | import java.io.Serializable; 16 | 17 | /** 18 | * @author eko.zhan 19 | * @version 1.0 20 | * @date 2021/6/29 20:09 21 | */ 22 | @Data 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | @Builder 26 | @Entity 27 | @Table(name = "attachment") 28 | public class Attachment implements Serializable { 29 | 30 | @Id 31 | @GeneratedValue(strategy = GenerationType.IDENTITY) 32 | private Long id; 33 | 34 | /** 35 | * 源文件路径 36 | */ 37 | private String path; 38 | 39 | /** 40 | * 目标文件路径 41 | */ 42 | private String targetPath; 43 | 44 | /** 45 | * 文件显示名称 46 | */ 47 | private String name; 48 | 49 | private Long size; 50 | 51 | /** 52 | * 文档大小,用于显示 53 | */ 54 | @Transient 55 | private String sizeAlias; 56 | 57 | /** 58 | * 0-待转换;1-已转换;-1-转换失败 59 | */ 60 | private Integer status; 61 | 62 | private LocalDateTime createTime; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/service/ConvertService.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc.service; 2 | 3 | import com.eastrobot.doc.model.entity.Attachment; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | 7 | /** 8 | * @author eko.zhan 9 | * @version 1.0 10 | * @date 2021/6/30 21:04 11 | */ 12 | public interface ConvertService { 13 | 14 | /** 15 | * 文件转换 16 | * @param attachment 17 | */ 18 | void exec(Attachment attachment) throws FileNotFoundException; 19 | 20 | /** 21 | * 文档转换 22 | */ 23 | void exec(File inputFile, File outputFile) throws FileNotFoundException; 24 | } 25 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/service/FileService.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc.service; 2 | 3 | import com.eastrobot.doc.model.entity.Attachment; 4 | import java.io.FileNotFoundException; 5 | import java.io.IOException; 6 | import org.springframework.web.multipart.MultipartFile; 7 | 8 | /** 9 | * @author eko.zhan 10 | * @version 1.0 11 | * @date 2021/6/29 20:08 12 | */ 13 | public interface FileService { 14 | 15 | /** 16 | * 上传文件并转换 17 | * @param multipartFile 18 | * @return 19 | */ 20 | Boolean upload(MultipartFile multipartFile); 21 | 22 | String loadData(Long id) throws IOException; 23 | 24 | /** 25 | * 获取指定目录下的文件列表 26 | * @return 27 | * @throws FileNotFoundException 28 | */ 29 | Iterable list() throws FileNotFoundException; 30 | 31 | void delete(Long id); 32 | } 33 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/service/WatermarkService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.service; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | /** 10 | * @author eko.zhan 11 | * @date 2018年9月1日 上午10:09:26 12 | * @version 1.0 13 | */ 14 | public interface WatermarkService { 15 | 16 | /** 17 | * 给源文件加水印 18 | * @author eko.zhan at 2018年9月1日 下午4:42:15 19 | * @param originFile 20 | * @param watermark 21 | * @return 22 | * @throws IOException 23 | */ 24 | public byte[] handle(File originFile, String watermark) throws IOException; 25 | /** 26 | * 给源文件加水印 27 | * @author eko.zhan at 2018年9月1日 下午4:42:15 28 | * @param originFile 29 | * @param watermark 30 | * @return 31 | * @throws IOException 32 | */ 33 | public byte[] handle(File originFile, String watermark, String color) throws IOException; 34 | } 35 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/service/impl/ConvertServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc.service.impl; 2 | 3 | import com.eastrobot.doc.config.SystemConstants; 4 | import com.eastrobot.doc.config.WebappContext; 5 | import com.eastrobot.doc.dao.AttachmentRepository; 6 | import com.eastrobot.doc.model.entity.Attachment; 7 | import com.eastrobot.doc.service.ConvertService; 8 | import java.io.File; 9 | import java.io.FileNotFoundException; 10 | import javax.annotation.Resource; 11 | import javax.servlet.http.HttpServletRequest; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.apache.commons.io.FilenameUtils; 14 | import org.artofsolving.jodconverter.OfficeDocumentConverter; 15 | import org.springframework.scheduling.annotation.Async; 16 | import org.springframework.stereotype.Service; 17 | import org.springframework.util.StopWatch; 18 | import org.springframework.web.context.request.RequestContextHolder; 19 | import org.springframework.web.context.request.ServletRequestAttributes; 20 | 21 | /** 22 | * @author eko.zhan 23 | * @version 1.0 24 | * @date 2021/6/30 21:06 25 | */ 26 | @Service 27 | @Slf4j 28 | public class ConvertServiceImpl implements ConvertService { 29 | 30 | @Resource 31 | AttachmentRepository attachmentRepository; 32 | 33 | @Async 34 | @Override 35 | public void exec(Attachment attachment) throws FileNotFoundException { 36 | // 调用之前需要共享 ServletRequestAttributes 37 | HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder 38 | .currentRequestAttributes())).getRequest(); 39 | WebappContext webappContext = WebappContext.get(request.getServletContext()); 40 | OfficeDocumentConverter converter = webappContext.getDocumentConverter(); 41 | 42 | 43 | File inputFile = new File(attachment.getPath()); 44 | File outputFile = new File(attachment.getTargetPath()); 45 | 46 | String inputExtension = FilenameUtils.getExtension(inputFile.getName()); 47 | 48 | StopWatch stopWatch = new StopWatch(); 49 | stopWatch.start("文件转换任务-" + attachment.getName()); 50 | try { 51 | converter.convert(inputFile, outputFile); 52 | 53 | stopWatch.stop(); 54 | log.info(stopWatch.prettyPrint()); 55 | 56 | attachment.setStatus(1); 57 | attachmentRepository.save(attachment); 58 | } catch (Exception e) { 59 | log.error(String 60 | .format("failed conversion: %s [%db] to %s; %s; input file: %s", inputExtension, 61 | inputFile.length(), SystemConstants.OUTPUT_EXTENSION, e, inputFile.getName())); 62 | 63 | attachment.setStatus(-1); 64 | attachmentRepository.save(attachment); 65 | 66 | throw new FileNotFoundException(); 67 | } 68 | } 69 | 70 | @Async 71 | @Override 72 | public void exec(File inputFile, File outputFile) throws FileNotFoundException { 73 | // 调用之前需要共享 ServletRequestAttributes 74 | HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder 75 | .currentRequestAttributes())).getRequest(); 76 | WebappContext webappContext = WebappContext.get(request.getServletContext()); 77 | OfficeDocumentConverter converter = webappContext.getDocumentConverter(); 78 | String inputExtension = FilenameUtils.getExtension(inputFile.getName()); 79 | 80 | try { 81 | long startTime = System.currentTimeMillis(); 82 | converter.convert(inputFile, outputFile); 83 | long conversionTime = System.currentTimeMillis() - startTime; 84 | log.info(String.format("successful conversion: %s [%db] to %s in %dms", inputExtension, 85 | inputFile.length(), SystemConstants.OUTPUT_EXTENSION, conversionTime)); 86 | } catch (Exception e) { 87 | log.error(String 88 | .format("failed conversion: %s [%db] to %s; %s; input file: %s", inputExtension, 89 | inputFile.length(), SystemConstants.OUTPUT_EXTENSION, e, inputFile.getName())); 90 | throw new FileNotFoundException(); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/service/impl/FileServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc.service.impl; 2 | 3 | import com.eastrobot.doc.config.SystemConstants; 4 | import com.eastrobot.doc.dao.AttachmentRepository; 5 | import com.eastrobot.doc.model.entity.Attachment; 6 | import com.eastrobot.doc.service.ConvertService; 7 | import com.eastrobot.doc.service.FileService; 8 | import com.eastrobot.doc.util.FileExtensionUtils; 9 | import com.eastrobot.doc.util.HtmlUtils; 10 | import com.google.common.collect.Streams; 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.FileNotFoundException; 14 | import java.io.IOException; 15 | import java.time.LocalDateTime; 16 | import java.util.Optional; 17 | import java.util.stream.Collectors; 18 | import javax.annotation.Resource; 19 | import lombok.extern.slf4j.Slf4j; 20 | import org.apache.commons.io.FileUtils; 21 | import org.apache.commons.io.FilenameUtils; 22 | import org.apache.commons.io.IOUtils; 23 | import org.apache.commons.lang3.StringUtils; 24 | import org.springframework.stereotype.Service; 25 | import org.springframework.util.FileCopyUtils; 26 | import org.springframework.util.ResourceUtils; 27 | import org.springframework.web.context.request.RequestContextHolder; 28 | import org.springframework.web.context.request.ServletRequestAttributes; 29 | import org.springframework.web.multipart.MultipartFile; 30 | 31 | /** 32 | * @author eko.zhan 33 | * @version 1.0 34 | * @date 2021/6/29 20:11 35 | */ 36 | @Service 37 | @Slf4j 38 | public class FileServiceImpl implements FileService { 39 | 40 | @Resource 41 | ConvertService convertService; 42 | 43 | @Resource 44 | AttachmentRepository attachmentRepository; 45 | 46 | @Override 47 | public Boolean upload(MultipartFile multipartFile) { 48 | try { 49 | File targetDir = ResourceUtils.getFile("classpath:static/DATAS/"); 50 | String inputExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); 51 | 52 | Attachment attachment = Attachment.builder() 53 | .name(multipartFile.getOriginalFilename()) 54 | .size(multipartFile.getSize()) 55 | // 待转换 56 | .status(0) 57 | .createTime(LocalDateTime.now()) 58 | .build(); 59 | attachmentRepository.save(attachment); 60 | String inputFilename = attachment.getId() + ""; 61 | 62 | File file = new File(targetDir.getAbsolutePath() + "/" + inputFilename + "." + inputExtension); 63 | FileCopyUtils.copy(multipartFile.getBytes(), file); 64 | 65 | File outputFile = new File(targetDir.getAbsolutePath() + "/" + inputFilename + 66 | "/" + inputFilename + "." + SystemConstants.OUTPUT_EXTENSION); 67 | 68 | // 保存源文件和目标文件的路径 69 | attachment.setPath(file.getPath()); 70 | attachment.setTargetPath(outputFile.getPath()); 71 | attachmentRepository.save(attachment); 72 | 73 | // 异步执行文件转换 74 | ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) (RequestContextHolder 75 | .currentRequestAttributes()); 76 | RequestContextHolder.setRequestAttributes(servletRequestAttributes, true); 77 | convertService.exec(attachment); 78 | } catch (IOException e) { 79 | return false; 80 | } 81 | return true; 82 | } 83 | 84 | @Override 85 | public String loadData(Long id) throws IOException { 86 | 87 | Optional attachmentOptional = attachmentRepository.findById(id); 88 | 89 | if (attachmentOptional.isPresent()) { 90 | Attachment attachment = attachmentOptional.get(); 91 | File file = ResourceUtils.getFile(attachment.getPath()); 92 | 93 | if (attachment.getStatus()!=1) { 94 | // 转换中 95 | return String.format(" 文件 [%s] 正在转换中", file.getName()); 96 | } 97 | 98 | String basename = FilenameUtils.getBaseName(file.getName()); 99 | File targetFile = new File(file.getParent() + "/" + basename + "/" + basename + "." 100 | + SystemConstants.OUTPUT_EXTENSION); 101 | if (targetFile.exists()) { 102 | //logger.debug(HtmlUtils.getFileEncoding(targetFile)); 103 | String data = IOUtils.toString(new FileInputStream(targetFile), HtmlUtils.getFileEncoding(targetFile)); 104 | //logger.debug(data); 105 | //获取文件头部,每个文件转换出的html头部样式都不一样,动态获取 106 | //截图 ") + 1); 112 | header = HtmlUtils.replaceCharset(header); 113 | } catch (StringIndexOutOfBoundsException e) { 114 | e.printStackTrace(); 115 | log.error("html页面数据解析异常"); 116 | } 117 | 118 | // HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest(); 119 | // request.getSession().setAttribute(SystemConstants.HTML_HEADER, header); 120 | //TODO 如果是网络图片,如何处理? 121 | //TODO 保存后再次打开html文档,如何处理? 122 | //data = HtmlUtils.replaceHtmlTag(data, "img", "src", "src=\"" + request.getContextPath() + "/index/loadFileImg?name=" + name + "&imgname=", "\""); 123 | return data; 124 | } 125 | return "当前文档转换失败"; 126 | } 127 | 128 | return id + "对应的文件不存在"; 129 | } 130 | 131 | @Override 132 | public Iterable list() throws FileNotFoundException { 133 | return Streams.stream(attachmentRepository.findAll()) 134 | .peek(attachment -> { 135 | attachment.setSizeAlias(FileExtensionUtils.readFilesize(attachment.getSize())); 136 | }) 137 | .collect(Collectors.toList()); 138 | // File dir = ResourceUtils.getFile("classpath:static/DATAS"); 139 | // File[] files = dir.listFiles(); 140 | // List list = Lists.newArrayList(); 141 | // for (File file : files) { 142 | // if (file.isFile()) { 143 | // list.add(Attachment 144 | // .builder() 145 | // .path(file.getPath()) 146 | // .name(file.getName()) 147 | // .size(file.length()) 148 | // .build()); 149 | // } 150 | // } 151 | // return list; 152 | } 153 | 154 | @Override 155 | public void delete(Long id) { 156 | attachmentRepository.findById(id) 157 | .ifPresent(attachment -> { 158 | //TODO windows操作系统上如果html文件被占用则无法删除,是否可以用 File.creteTempFile 来解决? 159 | try { 160 | if (StringUtils.isNotBlank(attachment.getTargetPath())) { 161 | // html 路径,需要删除 parent 文件夹 162 | File targetFile = new File(attachment.getTargetPath()); 163 | if (targetFile.exists()){ 164 | FileUtils.deleteDirectory(targetFile.getParentFile()); 165 | } 166 | } 167 | 168 | if (StringUtils.isNotBlank(attachment.getPath())) { 169 | File file = new File(attachment.getPath()); 170 | if (file.exists()){ 171 | FileUtils.forceDelete(file); 172 | } 173 | } 174 | } catch (IOException e) { 175 | e.printStackTrace(); 176 | } 177 | 178 | attachmentRepository.delete(attachment); 179 | 180 | }); 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/service/impl/WatermarkServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.service.impl; 5 | 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.FileOutputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.io.OutputStream; 12 | 13 | import javax.xml.namespace.QName; 14 | 15 | import org.apache.commons.lang3.StringUtils; 16 | import org.apache.poi.hwpf.HWPFDocument; 17 | import org.apache.poi.util.IOUtils; 18 | import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy; 19 | import org.apache.poi.xwpf.usermodel.XWPFDocument; 20 | import org.apache.poi.xwpf.usermodel.XWPFHeader; 21 | import org.apache.poi.xwpf.usermodel.XWPFParagraph; 22 | import org.apache.xmlbeans.XmlObject; 23 | import org.springframework.stereotype.Service; 24 | 25 | import com.eastrobot.doc.service.WatermarkService; 26 | 27 | /** 28 | * @author eko.zhan 29 | * @date 2018年9月1日 上午10:11:26 30 | * @version 1.0 31 | */ 32 | @Service 33 | public class WatermarkServiceImpl implements WatermarkService { 34 | 35 | private final static String DEFAULT_WATERMARK = "powered by eko.zhan"; 36 | private final static String DEFAULT_FONT_COLOR = "#d8d8d8"; 37 | 38 | @Override 39 | public byte[] handle(File originFile, String watermark) throws IOException { 40 | return handle(originFile, watermark, DEFAULT_FONT_COLOR); 41 | } 42 | 43 | @Override 44 | public byte[] handle(File originFile, String watermark, String color) throws IOException { 45 | watermark = StringUtils.isBlank(watermark)?DEFAULT_WATERMARK:watermark; 46 | color = StringUtils.isBlank(color)?DEFAULT_FONT_COLOR:color; 47 | if (originFile.getName().toLowerCase().endsWith("docx")) { 48 | try (InputStream in = new FileInputStream(originFile)){ 49 | XWPFDocument doc = new XWPFDocument(in); 50 | addWaterMark(doc, watermark, color); 51 | try (OutputStream out = new FileOutputStream(originFile)){ 52 | doc.write(out); 53 | doc.close(); 54 | } 55 | } 56 | return IOUtils.toByteArray(new FileInputStream(originFile)); 57 | } else if (originFile.getName().toLowerCase().endsWith("doc")) { 58 | try (InputStream in = new FileInputStream(originFile)){ 59 | HWPFDocument doc = new HWPFDocument(in); 60 | addWaterMark(doc, watermark, color); 61 | try (OutputStream out = new FileOutputStream(originFile)){ 62 | doc.write(out); 63 | doc.close(); 64 | } 65 | } 66 | return IOUtils.toByteArray(new FileInputStream(originFile)); 67 | } 68 | return null; 69 | } 70 | 71 | 72 | 73 | 74 | private void addWaterMark(Object obj, String watermark, String color) { 75 | if (obj instanceof XWPFDocument) { 76 | XWPFDocument doc = (XWPFDocument) obj; 77 | // create header-footer 78 | XWPFHeaderFooterPolicy headerFooterPolicy = doc.getHeaderFooterPolicy(); 79 | if (headerFooterPolicy == null) headerFooterPolicy = doc.createHeaderFooterPolicy(); 80 | 81 | // create default Watermark - fill color black and not rotated 82 | headerFooterPolicy.createWatermark(watermark); 83 | 84 | // get the default header 85 | // Note: createWatermark also sets FIRST and EVEN headers 86 | // but this code does not updating those other headers 87 | XWPFHeader header = headerFooterPolicy.getHeader(XWPFHeaderFooterPolicy.DEFAULT); 88 | XWPFParagraph paragraph = header.getParagraphArray(0); 89 | 90 | // get com.microsoft.schemas.vml.CTShape where fill color and rotation is set 91 | XmlObject[] xmlobjects = paragraph.getCTP().getRArray(0).getPictArray(0).selectChildren(new QName("urn:schemas-microsoft-com:vml", "shape")); 92 | if (xmlobjects.length > 0) { 93 | com.microsoft.schemas.vml.CTShape ctshape = (com.microsoft.schemas.vml.CTShape)xmlobjects[0]; 94 | // set fill color 95 | ctshape.setFillcolor(color); 96 | // set rotation 97 | ctshape.setStyle(ctshape.getStyle() + ";rotation:315"); 98 | } 99 | } else if (obj instanceof HWPFDocument) { 100 | 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/util/FileExtensionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import java.text.DecimalFormat; 7 | import org.apache.commons.io.FilenameUtils; 8 | import org.apache.commons.lang3.ArrayUtils; 9 | 10 | /** 11 | * 12 | * @author eko.zhan 13 | * @date 2017年12月21日 下午3:10:34 14 | * @version 1.0 15 | */ 16 | public class FileExtensionUtils { 17 | 18 | private static String[] videoArray = new String[]{"mp4", "avi", "wma", "rmvb", "rm", "flash", "mid", "3gp"}; 19 | private static String[] imageArray = new String[]{"jpg", "jpeg", "png", "gif", "ico", "bmp"}; 20 | private static String[] audioArray = new String[]{"mp3", "wav", "ogg"}; 21 | private static String[] officeArray = new String[]{"doc", "docx", "xls", "xlsx", "ppt", "pptx"}; 22 | 23 | /** 24 | * 是否是视频文件 25 | * @author eko.zhan at 2017年12月21日 下午3:38:28 26 | * @return 27 | */ 28 | public static Boolean isVideo(String filename){ 29 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 30 | if (ArrayUtils.contains(videoArray, extension)){ 31 | return true; 32 | } 33 | return false; 34 | } 35 | /** 36 | * 是否是图片 37 | * @author eko.zhan at 2017年12月21日 下午3:47:18 38 | * @param filename 39 | * @return 40 | */ 41 | public static Boolean isImage(String filename){ 42 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 43 | if (ArrayUtils.contains(imageArray, extension)){ 44 | return true; 45 | } 46 | return false; 47 | } 48 | /** 49 | * 是否是Office文件 50 | * @author eko.zhan at Jan 3, 2018 5:30:52 PM 51 | * @param filename 52 | * @return 53 | */ 54 | public static Boolean isOffice(String filename){ 55 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 56 | if (ArrayUtils.contains(officeArray, extension)){ 57 | return true; 58 | } 59 | return false; 60 | } 61 | /** 62 | * 是否是音频文件 63 | * @author eko.zhan at Jan 5, 2018 3:41:36 PM 64 | * @param filename 65 | * @return 66 | */ 67 | public static Boolean isAudio(String filename) { 68 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 69 | if (ArrayUtils.contains(audioArray, extension)){ 70 | return true; 71 | } 72 | return false; 73 | } 74 | /** 75 | * 是否是Excel文件 76 | * @author eko.zhan at Aug 7, 2018 11:33:06 AM 77 | * @param filename 78 | * @return 79 | */ 80 | public static Boolean isExcel(String filename){ 81 | String[] arr = new String[]{"xls", "xlsx"}; 82 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 83 | if (ArrayUtils.contains(arr, extension)){ 84 | return true; 85 | } 86 | return false; 87 | } 88 | /** 89 | * 是否是Word文件 90 | * @author eko.zhan at Aug 7, 2018 11:33:06 AM 91 | * @param filename 92 | * @return 93 | */ 94 | public static Boolean isWord(String filename){ 95 | String[] arr = new String[]{"doc", "docx"}; 96 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 97 | if (ArrayUtils.contains(arr, extension)){ 98 | return true; 99 | } 100 | return false; 101 | } 102 | /** 103 | * 是否是 ppt 文件 104 | * @author eko.zhan at 2018年9月1日 上午10:16:11 105 | * @param filename 106 | * @return 107 | */ 108 | public static Boolean isPpt(String filename) { 109 | String[] arr = new String[]{"ppt", "pptx"}; 110 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 111 | if (ArrayUtils.contains(arr, extension)){ 112 | return true; 113 | } 114 | return false; 115 | } 116 | /** 117 | * 是否是 Word 或 Excel 文件 118 | * @author eko.zhan at Aug 7, 2018 11:37:50 AM 119 | * @param filename 120 | * @return 121 | */ 122 | public static Boolean isWordOrExcel(String filename){ 123 | return isWord(filename) || isExcel(filename); 124 | } 125 | /** 126 | * 是否是 office 或 pdf 文件 127 | * @author eko.zhan at Aug 7, 2018 11:45:10 AM 128 | * @param filename 129 | * @return 130 | */ 131 | public static Boolean isOfficeOrPdf(String filename){ 132 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 133 | if (isOffice(filename) || "pdf".equals(extension)){ 134 | return Boolean.TRUE; 135 | }else{ 136 | return Boolean.FALSE; 137 | } 138 | } 139 | 140 | /** 141 | * 是否是 html 文件 142 | */ 143 | public static Boolean isHtml(String filename) { 144 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 145 | if ("html".equals(extension) || "htm".equals(extension)) { 146 | return Boolean.TRUE; 147 | } else { 148 | return Boolean.FALSE; 149 | } 150 | } 151 | 152 | /** 153 | * 是否是 pdf 文件 154 | */ 155 | public static Boolean isPdf(String filename) { 156 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 157 | if ("pdf".equals(extension)) { 158 | return Boolean.TRUE; 159 | } else { 160 | return Boolean.FALSE; 161 | } 162 | } 163 | 164 | public static String readFilesize(Long size) { 165 | final String[] units = new String[] {"B", "KB", "MB", "GB", "TB"}; 166 | int digitGroups = (int)(Math.log10(size) / Math.log10(1024)); 167 | return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) 168 | + " " + units[digitGroups]; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/util/HtmlUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.util.regex.Matcher; 9 | import java.util.regex.Pattern; 10 | 11 | import org.apache.commons.io.FileUtils; 12 | import org.apache.commons.lang3.StringUtils; 13 | import org.mozilla.universalchardet.UniversalDetector; 14 | 15 | /** 16 | * @author eko.zhan 17 | * @date 2017年8月9日 下午8:30:29 18 | * @version 1.0 19 | */ 20 | public class HtmlUtils { 21 | 22 | public static final String UTF8 = "UTF-8"; 23 | 24 | //TODO 是否有思考 excel 和 ppt 转换后的头部? 25 | public static final String HEAD_TEMPLATE = 26 | "" + 27 | "" + 28 | "" + 29 | "" + 37 | ""; 38 | 39 | public static final String FOOT_TEMPLATE = ""; 40 | 41 | /** 42 | * http://blog.csdn.net/huweijun_2012/article/details/51900814 43 | * 替换指定标签的属性和值 44 | * @param str 需要处理的字符串 45 | * @param tag 标签名称 46 | * @param tagAttrib 要替换的标签属性值 47 | * @param startTag 新标签开始标记 48 | * @param endTag 新标签结束标记 49 | * @return 50 | * @author huweijun 51 | * @date 2016年7月13日 下午7:15:32 52 | */ 53 | public static String replaceHtmlTag(String str, String tag, String tagAttrib, String startTag, String endTag) { 54 | String regxpForTag = "<\\s*" + tag + "\\s+([^>]*)\\s*" ; 55 | String regxpForTagAttrib = tagAttrib + "=\\s*\"([^\"]+)\"" ; 56 | Pattern patternForTag = Pattern.compile (regxpForTag,Pattern. CASE_INSENSITIVE ); 57 | Pattern patternForAttrib = Pattern.compile (regxpForTagAttrib,Pattern. CASE_INSENSITIVE ); 58 | Matcher matcherForTag = patternForTag.matcher(str); 59 | StringBuffer sb = new StringBuffer(); 60 | boolean result = matcherForTag.find(); 61 | while (result) { 62 | StringBuffer sbreplace = new StringBuffer( "<"+tag+" "); 63 | Matcher matcherForAttrib = patternForAttrib.matcher(matcherForTag.group(1)); 64 | if (matcherForAttrib.find()) { 65 | String attributeStr = matcherForAttrib.group(1); 66 | matcherForAttrib.appendReplacement(sbreplace, startTag + attributeStr + endTag); 67 | } 68 | matcherForAttrib.appendTail(sbreplace); 69 | matcherForTag.appendReplacement(sb, sbreplace.toString()); 70 | result = matcherForTag.find(); 71 | } 72 | matcherForTag.appendTail(sb); 73 | return sb.toString(); 74 | } 75 | 76 | /** 77 | * 将 data 中的编码修改为 utf-8 78 | * @author eko.zhan at 2017年8月11日 上午9:54:34 79 | * @param data 80 | * @return 81 | */ 82 | public static String replaceCharset(String data){ 83 | return StringUtils.replaceAll(data, "(?i)CONTENT=\"text/html; charset=gb2312\"", "CONTENT=\"text/html; charset=utf-8\""); 84 | } 85 | 86 | /** 87 | * 获取文件编码 88 | * @author eko.zhan at Jul 3, 2017 1:54:50 PM 89 | * @param file 90 | * @return 91 | * @throws IOException 92 | */ 93 | public static String getFileEncoding(File file) throws IOException{ 94 | UniversalDetector detector = new UniversalDetector(null); 95 | byte[] bytes = FileUtils.readFileToByteArray(file); 96 | detector.handleData(bytes, 0, bytes.length); 97 | detector.dataEnd(); 98 | return detector.getDetectedCharset(); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/util/MammothUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | import org.zwobble.mammoth.DocumentConverter; 10 | import org.zwobble.mammoth.Result; 11 | 12 | /** 13 | * @author eko.zhan 14 | * @date 2017年8月3日 下午8:45:46 15 | * @version 1.0 16 | */ 17 | public class MammothUtils { 18 | 19 | /** 20 | * word 转 html 21 | * @author eko.zhan at 2017年8月3日 下午8:51:10 22 | * @param file 23 | * @return 24 | */ 25 | public static String wordToHtml(File file){ 26 | //java.util.zip.ZipException: error in opening zip file 27 | try { 28 | DocumentConverter converter = new DocumentConverter(); 29 | Result result = converter.convertToHtml(file); 30 | String content = result.getValue(); 31 | return content; 32 | } catch (IOException e) { 33 | e.printStackTrace(); 34 | } 35 | return ""; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/util/OpenOfficeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | /** 6 | * @author eko.zhan 7 | * @date 2017年8月8日 下午1:47:20 8 | * @version 1.0 9 | */ 10 | public class OpenOfficeUtils { 11 | 12 | 13 | } 14 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/util/POIUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.IOException; 10 | import javax.xml.parsers.DocumentBuilderFactory; 11 | import javax.xml.parsers.ParserConfigurationException; 12 | import javax.xml.transform.OutputKeys; 13 | import javax.xml.transform.Transformer; 14 | import javax.xml.transform.TransformerException; 15 | import javax.xml.transform.TransformerFactory; 16 | import javax.xml.transform.TransformerFactoryConfigurationError; 17 | import javax.xml.transform.dom.DOMSource; 18 | import javax.xml.transform.stream.StreamResult; 19 | import org.apache.commons.io.IOUtils; 20 | import org.apache.poi.hwpf.HWPFDocumentCore; 21 | import org.apache.poi.hwpf.converter.WordToHtmlConverter; 22 | import org.apache.poi.hwpf.converter.WordToHtmlUtils; 23 | import org.w3c.dom.Document; 24 | 25 | /** 26 | * @author eko.zhan 27 | * @date 2017年8月3日 下午8:34:35 28 | * @version 1.0 29 | */ 30 | public class POIUtils { 31 | 32 | /** 33 | * word to html 34 | * @author eko.zhan at 2017年8月3日 下午8:51:23 35 | * @param file 36 | * @return 37 | * @throws ParserConfigurationException 38 | * @throws FileNotFoundException 39 | * @throws IOException 40 | * @throws TransformerException 41 | */ 42 | public static String wordToHtml(File file){ 43 | String result = ""; 44 | ByteArrayOutputStream out = null; 45 | try { 46 | HWPFDocumentCore wordDocument = WordToHtmlUtils.loadDoc(file); 47 | 48 | WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter( 49 | DocumentBuilderFactory.newInstance().newDocumentBuilder() 50 | .newDocument()); 51 | 52 | wordToHtmlConverter.processDocument(wordDocument); 53 | Document htmlDocument = wordToHtmlConverter.getDocument(); 54 | out = new ByteArrayOutputStream(); 55 | DOMSource domSource = new DOMSource(htmlDocument); 56 | StreamResult streamResult = new StreamResult(out); 57 | 58 | TransformerFactory tf = TransformerFactory.newInstance(); 59 | Transformer serializer = tf.newTransformer(); 60 | serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 61 | serializer.setOutputProperty(OutputKeys.INDENT, "yes"); 62 | serializer.setOutputProperty(OutputKeys.METHOD, "html"); 63 | serializer.transform(domSource, streamResult); 64 | 65 | result = new String(out.toByteArray()); 66 | } catch (FileNotFoundException e) { 67 | e.printStackTrace(); 68 | } catch (IllegalArgumentException e) { 69 | e.printStackTrace(); 70 | } catch (IOException e) { 71 | e.printStackTrace(); 72 | } catch (ParserConfigurationException e) { 73 | e.printStackTrace(); 74 | } catch (TransformerFactoryConfigurationError e) { 75 | e.printStackTrace(); 76 | } catch (TransformerException e) { 77 | e.printStackTrace(); 78 | } finally { 79 | IOUtils.closeQuietly(out); 80 | } 81 | return result; 82 | } 83 | 84 | /** 85 | * excel to html 86 | * @author eko.zhan at 2017年8月3日 下午9:36:51 87 | * @param file 88 | * @return 89 | */ 90 | public static String excelToHtml(File file){ 91 | String result = ""; 92 | 93 | return result; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/AbstractProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | 8 | /** 9 | * @author eko.zhan 10 | * @date 2018年9月17日 下午4:37:19 11 | * @version 1.0 12 | */ 13 | public abstract class AbstractProcessor { 14 | 15 | protected File file; 16 | protected File imageFile; 17 | 18 | public AbstractProcessor(File file, File imageFile) { 19 | this.file = file; 20 | this.imageFile = imageFile; 21 | } 22 | 23 | /** 24 | * 执行文件转换,将 file 添加 imageFile 水印 25 | * @author eko.zhan at 2018年9月17日 下午6:08:24 26 | * @throws WatermarkException 27 | */ 28 | public abstract void process() throws WatermarkException; 29 | } 30 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/ExcelProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | import org.apache.commons.io.FileUtils; 10 | import org.docx4j.openpackaging.exceptions.Docx4JException; 11 | import org.docx4j.openpackaging.packages.SpreadsheetMLPackage; 12 | import org.docx4j.openpackaging.parts.SpreadsheetML.WorksheetPart; 13 | import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage; 14 | import org.docx4j.relationships.Relationship; 15 | import org.xlsx4j.exceptions.Xlsx4jException; 16 | import org.xlsx4j.sml.CTSheetBackgroundPicture; 17 | 18 | /** 19 | * @author eko.zhan 20 | * @date 2018年9月17日 下午1:48:10 21 | * @version 1.0 22 | */ 23 | public class ExcelProcessor extends AbstractProcessor { 24 | 25 | private SpreadsheetMLPackage excelMLPackage; 26 | 27 | public ExcelProcessor(File file, File imageFile) { 28 | super(file, imageFile); 29 | } 30 | 31 | /** 32 | * 传入一个 xlsx 文件,和一个水印文件,给这个 xlsx 文件加水印 33 | * @author eko.zhan at 2018年9月17日 下午2:10:50 34 | * @throws Docx4JException 35 | * @throws Xlsx4jException 36 | */ 37 | @Override 38 | public void process() throws WatermarkException { 39 | try { 40 | SpreadsheetMLPackage excelMLPackage = SpreadsheetMLPackage.load(file); 41 | this.excelMLPackage = excelMLPackage; 42 | int size = excelMLPackage.getWorkbookPart().getContents().getSheets().getSheet().size(); 43 | for (int i=0;i 57 | * @param worksheet 58 | * @throws Docx4JException 59 | * @throws Exception 60 | * @throws IOException 61 | */ 62 | private void createBgPic(WorksheetPart worksheet) throws Docx4JException { 63 | CTSheetBackgroundPicture ctSheetBackgroundPicture = org.xlsx4j.jaxb.Context.getsmlObjectFactory().createCTSheetBackgroundPicture(); 64 | worksheet.getContents().setPicture(ctSheetBackgroundPicture); 65 | try { 66 | BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(excelMLPackage, worksheet, FileUtils.readFileToByteArray(imageFile)); 67 | Relationship sourceRelationship = imagePart.getSourceRelationships().get(0); 68 | String imageRelId = sourceRelationship.getId(); 69 | ctSheetBackgroundPicture.setId(imageRelId); 70 | } catch (Exception e) { 71 | e.printStackTrace(); 72 | } 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/FontImage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.awt.Color; 7 | import java.awt.Font; 8 | import java.awt.Graphics2D; 9 | import java.awt.Transparency; 10 | import java.awt.font.FontRenderContext; 11 | import java.awt.geom.AffineTransform; 12 | import java.awt.geom.Rectangle2D; 13 | import java.awt.image.BufferedImage; 14 | import java.io.File; 15 | import java.io.IOException; 16 | import java.util.Date; 17 | 18 | import javax.imageio.ImageIO; 19 | 20 | import org.apache.commons.lang3.time.DateFormatUtils; 21 | 22 | /** 23 | * copy from https://github.com/puyulin/learn_java 24 | * @author eko.zhan 25 | * @date 2018年9月18日 上午10:11:03 26 | * @version 1.0 27 | */ 28 | public class FontImage { 29 | 30 | /** 31 | * 根据指定的文本创建图片 32 | * @author eko.zhan at 2018年9月18日 上午10:14:44 33 | * @param text 34 | * @throws WatermarkException 35 | */ 36 | public static File createImage(String text) throws WatermarkException { 37 | Font font = new Font("宋体", Font.PLAIN, 100); 38 | int[] arr = getWidthAndHeight(text, font); 39 | int width = arr[0]; 40 | int height = arr[1]; 41 | // 创建图片 42 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);//创建图片画布 43 | // Graphics gs = image.getGraphics(); 44 | // Graphics2D g = (Graphics2D)gs; 45 | // g.setColor(Color.WHITE); // 先用白色填充整张图片,也就是背景 46 | Graphics2D g = image.createGraphics(); 47 | // 增加下面代码使得背景透明 48 | image = g.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); 49 | g.dispose(); 50 | g = image.createGraphics(); 51 | // 背景透明代码结束 52 | // g.fillRect(0, 0, width, height);//画出矩形区域,以便于在矩形区域内写入文字 53 | g.setColor(new Color(242, 242, 242));// 再换成黑色,以便于写入文字 54 | g.setFont(font);// 设置画笔字体 55 | g.translate(10, 10); 56 | // g.rotate(0.1*Math.PI);//旋转 57 | g.rotate(0.16); 58 | g.drawString(text, 0, font.getSize());// 画出一行字符串 59 | g.dispose(); 60 | 61 | String property = System.getProperty("java.io.tmpdir"); 62 | File imageFile = new File(property + "/kbs-watermark-" + DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + ".png"); 63 | try { 64 | // 输出png图片 65 | ImageIO.write(image, "png", imageFile); 66 | } catch (IOException e) { 67 | throw new WatermarkException("IOException", e); 68 | } 69 | return imageFile; 70 | } 71 | 72 | private static int[] getWidthAndHeight(String text, Font font) { 73 | Rectangle2D r = font.getStringBounds(text, new FontRenderContext(AffineTransform.getScaleInstance(1, 1), false, false)); 74 | int unitHeight = (int) Math.floor(r.getHeight());// 75 | // 获取整个str用了font样式的宽度这里用四舍五入后+1保证宽度绝对能容纳这个字符串作为图片的宽度 76 | int width = (int) Math.round(r.getWidth()) + 20; 77 | // 把单个字符的高度+3保证高度绝对能容纳字符串作为图片的高度 78 | int height = unitHeight + 20; 79 | // System.out.println("width:" + width + ", height:" + height); 80 | return new int[]{width, height*2}; 81 | } 82 | } -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/ImageProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.awt.AlphaComposite; 7 | import java.awt.Graphics2D; 8 | import java.awt.Image; 9 | import java.awt.RenderingHints; 10 | import java.awt.image.BufferedImage; 11 | import java.io.File; 12 | import java.io.FileInputStream; 13 | import java.io.FileNotFoundException; 14 | import java.io.IOException; 15 | 16 | import javax.imageio.ImageIO; 17 | import javax.swing.ImageIcon; 18 | 19 | import org.apache.commons.io.FilenameUtils; 20 | import org.apache.poi.util.IOUtils; 21 | 22 | /** 23 | * @author eko.zhan 24 | * @date 2018年9月17日 下午5:22:56 25 | * @version 1.0 26 | */ 27 | public class ImageProcessor extends AbstractProcessor { 28 | 29 | public ImageProcessor(File file, File imageFile) { 30 | super(file, imageFile); 31 | } 32 | 33 | @Override 34 | public void process() throws WatermarkException { 35 | try { 36 | Image srcImage = ImageIO.read(file); 37 | BufferedImage bufferImg = new BufferedImage(srcImage.getWidth(null), srcImage.getHeight(null), BufferedImage.TYPE_INT_RGB); 38 | Graphics2D g = bufferImg.createGraphics(); 39 | g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); 40 | g.drawImage(srcImage.getScaledInstance(srcImage.getWidth(null), srcImage.getHeight(null), BufferedImage.TYPE_INT_RGB), 0, 0, null); 41 | ImageIcon imageIcon = new ImageIcon(IOUtils.toByteArray(new FileInputStream(imageFile))); 42 | Image img = imageIcon.getImage(); 43 | float alpha = 0.3f; 44 | g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); 45 | //水印图片设计在右下角 46 | g.drawImage(img, srcImage.getWidth(null)-img.getWidth(null)-10, srcImage.getHeight(null)-img.getHeight(null)-10, null); 47 | g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); 48 | g.dispose(); 49 | ImageIO.write(bufferImg, FilenameUtils.getExtension(file.getName()), file); 50 | } catch (FileNotFoundException e) { 51 | throw new WatermarkException("FileNotFoundException", e); 52 | } catch (IOException e) { 53 | throw new WatermarkException("IOException", e); 54 | } 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/PdfProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.FileNotFoundException; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | import java.net.MalformedURLException; 12 | 13 | import org.apache.poi.util.IOUtils; 14 | 15 | import com.itextpdf.text.BadElementException; 16 | import com.itextpdf.text.DocumentException; 17 | import com.itextpdf.text.Image; 18 | import com.itextpdf.text.Rectangle; 19 | import com.itextpdf.text.pdf.PdfContentByte; 20 | import com.itextpdf.text.pdf.PdfGState; 21 | import com.itextpdf.text.pdf.PdfReader; 22 | import com.itextpdf.text.pdf.PdfStamper; 23 | 24 | /** 25 | * @author eko.zhan 26 | * @date 2018年9月17日 下午4:36:50 27 | * @version 1.0 28 | */ 29 | public class PdfProcessor extends AbstractProcessor { 30 | 31 | public PdfProcessor(File file, File imageFile) { 32 | super(file, imageFile); 33 | } 34 | 35 | @Override 36 | public void process() throws WatermarkException { 37 | PdfReader reader = null; 38 | PdfStamper stamper = null; 39 | try { 40 | reader = new PdfReader(new FileInputStream(file)); 41 | stamper = new PdfStamper(reader, new FileOutputStream(file)); 42 | int pageNo = reader.getNumberOfPages(); 43 | // image watermark 44 | Image img = Image.getInstance(IOUtils.toByteArray(new FileInputStream(imageFile))); 45 | float w = Math.min(img.getScaledWidth(), 460); 46 | float h = Math.min(img.getScaledHeight(), 300); 47 | for (float f : img.matrix()) { 48 | System.out.println(f); 49 | } 50 | // transparency 51 | PdfGState gs = new PdfGState(); 52 | gs.setFillOpacity(0.1f); 53 | // properties 54 | PdfContentByte over; 55 | Rectangle pagesize; 56 | float x, y; 57 | // loop over every page 58 | for (int i = 1; i <= pageNo; i++) { 59 | pagesize = reader.getPageSizeWithRotation(i); 60 | x = (pagesize.getLeft() + pagesize.getRight()) / 2; 61 | y = (pagesize.getTop() + pagesize.getBottom()) / 2; 62 | over = stamper.getOverContent(i); 63 | over.saveState(); 64 | over.setGState(gs); 65 | System.out.println(w + ", " + h + ", " + (x - (w / 2)) + ", " + (y - (h / 2))); 66 | // 617.0, 400.0, -10.839996, 220.95999 67 | over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2)); 68 | over.restoreState(); 69 | } 70 | if (stamper!=null) { 71 | stamper.close(); 72 | } 73 | } catch (FileNotFoundException e) { 74 | throw new WatermarkException("FileNotFoundException", e); 75 | } catch (BadElementException e) { 76 | throw new WatermarkException("BadElementException", e); 77 | } catch (MalformedURLException e) { 78 | throw new WatermarkException("MalformedURLException", e); 79 | } catch (IOException e) { 80 | throw new WatermarkException("IOException", e); 81 | } catch (DocumentException e) { 82 | throw new WatermarkException("DocumentException", e); 83 | } finally { 84 | if (reader!=null) { 85 | reader.close(); 86 | } 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/PowerPointProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.awt.geom.Rectangle2D; 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.FileNotFoundException; 10 | import java.io.FileOutputStream; 11 | import java.io.IOException; 12 | 13 | import org.apache.commons.io.IOUtils; 14 | import org.apache.poi.sl.usermodel.PictureData.PictureType; 15 | import org.apache.poi.xslf.usermodel.XMLSlideShow; 16 | import org.apache.poi.xslf.usermodel.XSLFPictureData; 17 | import org.apache.poi.xslf.usermodel.XSLFPictureShape; 18 | import org.apache.poi.xslf.usermodel.XSLFSlideLayout; 19 | import org.apache.poi.xslf.usermodel.XSLFSlideMaster; 20 | import org.xlsx4j.exceptions.Xlsx4jException; 21 | 22 | /** 23 | * @author eko.zhan 24 | * @date 2018年9月17日 下午1:48:10 25 | * @version 1.0 26 | */ 27 | public class PowerPointProcessor extends AbstractProcessor { 28 | 29 | public PowerPointProcessor(File file, File imageFile) { 30 | super(file, imageFile); 31 | } 32 | /** 33 | * 传入一个 pptx 文件,和一个水印文件,给这个 pptx 文件加水印 34 | * @author eko.zhan at 2018年9月17日 下午2:10:50 35 | * @throws IOException 36 | * @throws 37 | * @throws Xlsx4jException 38 | */ 39 | @Override 40 | public void process() throws WatermarkException { 41 | XMLSlideShow pptx = null; 42 | FileOutputStream output = null; 43 | try { 44 | pptx = new XMLSlideShow(new FileInputStream(file)); 45 | XSLFPictureData pictureData = pptx.addPicture(imageFile, PictureType.PNG); 46 | for (int i=0;ieko.zhan 7 | * @date 2018年9月17日 下午4:38:13 8 | * @version 1.0 9 | */ 10 | @SuppressWarnings("serial") 11 | public class WatermarkException extends Exception { 12 | 13 | public WatermarkException(String msg) { 14 | super(msg); 15 | } 16 | 17 | public WatermarkException(String msg, Exception e) { 18 | super(msg, e); 19 | } 20 | 21 | public WatermarkException(String msg, Throwable t) { 22 | super(msg, t); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/WatermarkProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import org.apache.commons.io.FilenameUtils; 11 | import org.springframework.util.Assert; 12 | 13 | import com.eastrobot.doc.util.FileExtensionUtils; 14 | 15 | /** 16 | * 中央处理器 17 | * @author eko.zhan 18 | * @date 2018年9月18日 上午9:40:29 19 | * @version 1.0 20 | */ 21 | public class WatermarkProcessor { 22 | private static Map map = new HashMap(); 23 | 24 | /** 25 | * 图片水印 26 | * @author eko.zhan at 2018年9月18日 上午9:48:57 27 | * @param file 28 | * @param imageFile 29 | * @throws WatermarkException 30 | */ 31 | public static void process(File file, File imageFile) throws WatermarkException { 32 | AbstractProcessor processor = null; 33 | if (FileExtensionUtils.isWord(file.getName())) { 34 | processor = new WordProcessor(file, imageFile); 35 | } else if (FileExtensionUtils.isExcel(file.getName())) { 36 | processor = new ExcelProcessor(file, imageFile); 37 | } else if (FileExtensionUtils.isPpt(file.getName())) { 38 | processor = new PowerPointProcessor(file, imageFile); 39 | } else if (FileExtensionUtils.isPdf(file.getName())) { 40 | processor = new PdfProcessor(file, imageFile); 41 | } else if (FileExtensionUtils.isImage(file.getName())) { 42 | processor = new ImageProcessor(file, imageFile); 43 | } 44 | if (processor!=null) { 45 | processor.process(); 46 | }else { 47 | throw new WatermarkException("不支持文件格式为 " + FilenameUtils.getExtension(file.getName()) + " 的水印处理"); 48 | } 49 | } 50 | /** 51 | * 文本水印 52 | * @author eko.zhan at 2018年9月18日 上午11:08:08 53 | * @param file 54 | * @param text 55 | * @throws WatermarkException 56 | */ 57 | public static void process(File file, String text) throws WatermarkException { 58 | Assert.hasText(text, "水印文本不能为空"); 59 | //通过 text 生成 Image File 60 | if (map.get(text)==null) { 61 | map.put(text, FontImage.createImage(text)); 62 | } 63 | process(file, map.get(text)); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/watermark/WordProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | 11 | import javax.xml.bind.JAXBException; 12 | 13 | import org.docx4j.Docx4J; 14 | import org.docx4j.XmlUtils; 15 | import org.docx4j.openpackaging.exceptions.Docx4JException; 16 | import org.docx4j.openpackaging.packages.WordprocessingMLPackage; 17 | import org.docx4j.openpackaging.parts.PartName; 18 | import org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart; 19 | import org.docx4j.openpackaging.parts.WordprocessingML.ImagePngPart; 20 | import org.docx4j.openpackaging.parts.relationships.RelationshipsPart.AddPartBehaviour; 21 | import org.docx4j.relationships.Relationship; 22 | import org.docx4j.wml.Hdr; 23 | import org.docx4j.wml.SectPr; 24 | 25 | /** 26 | * @author eko.zhan 27 | * @date 2018年9月17日 上午11:04:42 28 | * @version 1.0 29 | */ 30 | public class WordProcessor extends AbstractProcessor { 31 | 32 | private WordprocessingMLPackage wordMLPackage; 33 | 34 | public WordProcessor(File file, File imageFile) { 35 | super(file, imageFile); 36 | } 37 | 38 | /** 39 | * 传入一个 word 文件,和一个水印文件,给这个 word文件加水印 40 | * @author eko.zhan at 2018年9月17日 上午11:09:56 41 | * @throws Docx4JException 42 | * @throws JAXBException 43 | * @throws IOException 44 | */ 45 | @Override 46 | public void process() throws WatermarkException { 47 | try { 48 | WordprocessingMLPackage wordMLPackage = Docx4J.load(file); 49 | this.wordMLPackage = wordMLPackage; 50 | SectPr sectPr = createSectPr(); 51 | wordMLPackage.getMainDocumentPart().getContents().getBody().setSectPr(sectPr); 52 | Docx4J.save(wordMLPackage, file); 53 | } catch (Docx4JException e) { 54 | throw new WatermarkException("Docx4JException", e); 55 | } catch (JAXBException e) { 56 | throw new WatermarkException("JAXBException", e); 57 | } catch (IOException e) { 58 | throw new WatermarkException("IOException", e); 59 | } 60 | } 61 | 62 | private SectPr createSectPr() throws JAXBException, Docx4JException, IOException { 63 | String openXML = "" 64 | // Word adds the background image in each of 3 header parts 65 | + "" 66 | + "" 67 | + "" 68 | 69 | + "" 70 | + "" 71 | + "" 72 | + "" 73 | +""; 74 | return (SectPr)XmlUtils.unmarshalString(openXML); 75 | } 76 | 77 | private Relationship createHeaderPart(String nameSuffix) throws Docx4JException, IOException, JAXBException { 78 | HeaderPart headerPart = new HeaderPart(new PartName("/word/header-" + nameSuffix + ".xml")); 79 | Relationship rel = wordMLPackage.getMainDocumentPart().addTargetPart(headerPart); 80 | setHdr(headerPart); 81 | return rel; 82 | } 83 | 84 | private void setHdr(HeaderPart headerPart) throws Docx4JException, IOException, JAXBException { 85 | ImagePngPart imagePart = new ImagePngPart(new PartName("/media/background.png")); 86 | try (InputStream in = new FileInputStream(imageFile)){ 87 | imagePart.setBinaryData(in); 88 | } 89 | Relationship rel = headerPart.addTargetPart(imagePart, AddPartBehaviour.REUSE_EXISTING); // the one image is shared by the 3 header parts 90 | 91 | String openXML = "" 92 | + "" 93 | + "" 94 | + "" 95 | +"" 96 | + "" 97 | + "" 98 | + "" 99 | +"" 100 | + "" 101 | + "" 102 | + "" 103 | + "" 104 | + "" 105 | + "" 106 | + "" 107 | + "" 108 | + "" 109 | + "" 110 | + "" 111 | + "" 112 | + "" 113 | + "" 114 | + "" 115 | + "" 116 | +"" 117 | + "" 118 | + "" 119 | +"" 120 | + "" 121 | + "" 122 | +"" 123 | +"" 124 | +"" 125 | +"" 126 | +""; 127 | 128 | Hdr hdr = (Hdr)XmlUtils.unmarshalString(openXML); 129 | headerPart.setJaxbElement(hdr); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/web/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.web.controller; 5 | 6 | import com.alibaba.fastjson.JSONObject; 7 | import com.eastrobot.doc.config.BaseController; 8 | import com.eastrobot.doc.dao.AttachmentRepository; 9 | import com.eastrobot.doc.model.entity.Attachment; 10 | import com.eastrobot.doc.service.FileService; 11 | import com.eastrobot.doc.util.HtmlUtils; 12 | import io.swagger.annotations.Api; 13 | import io.swagger.annotations.ApiImplicitParam; 14 | import io.swagger.annotations.ApiImplicitParams; 15 | import io.swagger.annotations.ApiOperation; 16 | import java.io.File; 17 | import java.io.FileInputStream; 18 | import java.io.FileNotFoundException; 19 | import java.io.FileOutputStream; 20 | import java.io.IOException; 21 | import java.util.Calendar; 22 | import java.util.Optional; 23 | import javax.annotation.Resource; 24 | import javax.servlet.http.HttpServletRequest; 25 | import lombok.extern.slf4j.Slf4j; 26 | import org.apache.commons.io.FilenameUtils; 27 | import org.apache.commons.io.IOUtils; 28 | import org.springframework.http.HttpHeaders; 29 | import org.springframework.http.HttpStatus; 30 | import org.springframework.http.MediaType; 31 | import org.springframework.http.ResponseEntity; 32 | import org.springframework.util.ResourceUtils; 33 | import org.springframework.web.bind.annotation.DeleteMapping; 34 | import org.springframework.web.bind.annotation.PathVariable; 35 | import org.springframework.web.bind.annotation.RequestMapping; 36 | import org.springframework.web.bind.annotation.RequestMethod; 37 | import org.springframework.web.bind.annotation.RequestParam; 38 | import org.springframework.web.bind.annotation.RestController; 39 | import org.springframework.web.multipart.MultipartFile; 40 | 41 | /** 42 | * @author eko.zhan 43 | * @date 2017年7月29日 上午9:44:36 44 | * @version 1.0 45 | */ 46 | @Api 47 | @RequestMapping("index") 48 | @RestController 49 | @Slf4j 50 | public class IndexController extends BaseController { 51 | 52 | private final String outputExtension = "html"; 53 | 54 | @Resource 55 | FileService fileService; 56 | 57 | @Resource 58 | AttachmentRepository attachmentRepository; 59 | 60 | /** 61 | * 文件列表 62 | * @author eko.zhan at 2017年8月9日 下午8:32:19 63 | * @return 64 | * @throws FileNotFoundException 65 | */ 66 | @ApiOperation(value="获取文件数据列表", notes="获取固定路径下的文件,并返回文件名,文件所在路径和文件大小") 67 | @RequestMapping(value="getDataList", method=RequestMethod.POST) 68 | public Iterable getDataList() throws FileNotFoundException{ 69 | return fileService.list(); 70 | } 71 | 72 | /** 73 | * 加载文件 74 | * @author eko.zhan at 2017年8月9日 下午8:32:30 75 | * @param id 76 | * @return 77 | * @throws FileNotFoundException 78 | * @throws IOException 79 | */ 80 | @ApiOperation(value="根据指定的文件id获取文件内容", notes="返回文件内容会自动过滤图片信息") 81 | @ApiImplicitParams({ 82 | @ApiImplicitParam(name="id", value="文件id", required=true, dataType="String") 83 | }) 84 | @RequestMapping(value="loadFileData", produces="text/plain;charset=utf-8", method=RequestMethod.POST) 85 | public String loadFileData(Long id) throws IOException{ 86 | return fileService.loadData(id); 87 | } 88 | 89 | /** 90 | * 加载 html 中的图片资源 91 | * @author eko.zhan at 2017年8月9日 下午8:32:06 92 | * @param id 93 | * @param imgname 94 | * @return 95 | * @throws IOException 96 | */ 97 | @ApiOperation(value="加载图片内容", notes="获取word文档中内嵌的图片资源,返回图片内容") 98 | @ApiImplicitParams({ 99 | @ApiImplicitParam(name="id", value="文件id", required=true, dataType="Long"), 100 | @ApiImplicitParam(name="imgname", value="图片名称", required=true, dataType="String") 101 | }) 102 | @RequestMapping(value="loadFileImg", method=RequestMethod.GET) 103 | public ResponseEntity loadFileImg(Long id, String imgname){ 104 | try { 105 | String basename = id + ""; 106 | File file = ResourceUtils.getFile("classpath:static/DATAS/" + basename + "/" + imgname); 107 | HttpHeaders headers = new HttpHeaders(); 108 | headers.setContentType(MediaType.IMAGE_PNG); 109 | return new ResponseEntity(IOUtils.toByteArray(new FileInputStream(file)), headers, HttpStatus.OK); 110 | } catch (FileNotFoundException e) { 111 | log.error("文件[" + id + "]不存在, " + e.getMessage()); 112 | } catch (IOException e) { 113 | log.error(e.getMessage()); 114 | e.printStackTrace(); 115 | } 116 | return null; 117 | } 118 | /** 119 | * 上传文件 120 | * @author eko.zhan at 2017年8月9日 下午8:32:39 121 | * @param uploadFile 122 | * @return 123 | */ 124 | @ApiOperation(value="上传文件", notes="") 125 | @ApiImplicitParams({ 126 | @ApiImplicitParam(name="uploadFile", value="待上传的文件", required=true, dataType="__file") 127 | }) 128 | @RequestMapping(value="uploadData", method=RequestMethod.POST) 129 | public JSONObject uploadData(@RequestParam("uploadFile") MultipartFile uploadFile){ 130 | JSONObject json = new JSONObject(); 131 | json.put("result", fileService.upload(uploadFile)?1:0); 132 | return json; 133 | } 134 | 135 | /** 136 | * 保存html内容 137 | * @author eko.zhan at 2017年8月9日 下午9:04:20 138 | * @param id 139 | * @param data 140 | * @throws IOException 141 | */ 142 | @ApiOperation(value="保存文件", notes="") 143 | @ApiImplicitParams({ 144 | @ApiImplicitParam(name="id", value="文件id", required=true, dataType="Long"), 145 | @ApiImplicitParam(name="data", value="文件内容", required=true, dataType="String") 146 | }) 147 | @RequestMapping(value="saveFileData", method=RequestMethod.POST) 148 | public JSONObject saveFileData(Long id, String data, HttpServletRequest request){ 149 | //TODO 这是一个伪保存,只是修改了 HTML 内容,并未修改 file 文件,如果用户单击下载,依然会存在问题 150 | //TODO 如果用户修改了图片,如何处理? 151 | JSONObject json = new JSONObject(); 152 | json.put("result", 1); 153 | try { 154 | //DONE 优化底层 DefaultDocumentFormatRegistry.java 后可实现html转docx 155 | //boolean is07Xml = false; //是否是07以后的文档(docx/xlsx/pptx/),如果是,需要将html转成97版本的office文件,再从97转成07,直接将html转成07存在问题 156 | Optional attachmentOptional = attachmentRepository.findById(id); 157 | 158 | if (!attachmentOptional.isPresent()) { 159 | json.put("result", 0); 160 | return json; 161 | } 162 | 163 | Attachment attachment = attachmentOptional.get(); 164 | 165 | File file = ResourceUtils.getFile(attachment.getPath()); 166 | String name = FilenameUtils.getName(attachment.getPath()); 167 | File newFile = new File(file.getParent() + "/" + Calendar.getInstance().getTimeInMillis() + "_" + name); 168 | if (!name.toLowerCase().endsWith("x")){ 169 | newFile = new File(file.getParent() + "/" + Calendar.getInstance().getTimeInMillis() + "_" + name + "x"); 170 | } 171 | String basename = FilenameUtils.getBaseName(file.getName()); 172 | File targetFile = new File(file.getParent() + "/" + basename + "/" + basename + "." + outputExtension); 173 | if (targetFile.exists()){ 174 | ///将html中的body内容替换为当前 data 数据 175 | ///String htmlData = IOUtils.toString(new FileInputStream(targetFile), HtmlUtils.getFileEncoding(targetFile)); 176 | // String htmlData = (String)request.getSession().getAttribute(SystemConstants.HTML_HEADER) + data + HtmlUtils.FOOT_TEMPLATE; 177 | 178 | String htmlData = data + HtmlUtils.FOOT_TEMPLATE; 179 | 180 | 181 | //DONE 如何处理文件编码?保存后尽管通过请求能访问中文内容,但是直接磁盘双击html文件显示乱码 182 | //add by eko.zhan at 2017-08-11 14:55 解决方案:重写Html头,编码修改为 utf-8 183 | ///IOUtils.write(htmlData.getBytes(HtmlUtils.UTF8), new FileOutputStream(targetFile)); 184 | IOUtils.write(htmlData.getBytes(), new FileOutputStream(targetFile)); 185 | 186 | //DONE 由于html文件编码不正确,导致转换成word后文件编码也不正确 187 | //add by eko.zhan at 2017-08-11 15:05 上面处理了html编码后,转换的编码问题也相应解决了 188 | //TODO 由html转换成doc会导致doc样式有误 189 | convert(targetFile, newFile); 190 | 191 | } 192 | } catch (IOException e) { 193 | json.put("result", 0); 194 | e.printStackTrace(); 195 | } 196 | return json; 197 | } 198 | 199 | /** 200 | * 删除文件 201 | * @author eko.zhan at 2017年8月9日 下午9:32:18 202 | * @param id 203 | * @return 204 | */ 205 | @ApiOperation(value="删除文件", notes="") 206 | @ApiImplicitParams({ 207 | @ApiImplicitParam(name="id", value="文件id", required=true, dataType="Long") 208 | }) 209 | @DeleteMapping("{id}") 210 | public void delete(@PathVariable("id") Long id){ 211 | fileService.delete(id); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/com/eastrobot/doc/web/controller/WatermarkController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.web.controller; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | import java.util.Date; 9 | 10 | import com.eastrobot.doc.config.BaseController; 11 | import com.eastrobot.doc.service.WatermarkService; 12 | import org.apache.commons.io.FileUtils; 13 | import org.apache.commons.io.FilenameUtils; 14 | import org.apache.commons.lang3.time.DateFormatUtils; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.core.io.ByteArrayResource; 17 | import org.springframework.http.HttpHeaders; 18 | import org.springframework.http.ResponseEntity; 19 | import org.springframework.util.ResourceUtils; 20 | import org.springframework.web.bind.annotation.PostMapping; 21 | import org.springframework.web.bind.annotation.RequestMapping; 22 | import org.springframework.web.bind.annotation.RequestParam; 23 | import org.springframework.web.bind.annotation.RestController; 24 | import org.springframework.web.multipart.MultipartFile; 25 | 26 | import io.swagger.annotations.ApiImplicitParam; 27 | import io.swagger.annotations.ApiImplicitParams; 28 | import io.swagger.annotations.ApiOperation; 29 | import lombok.extern.slf4j.Slf4j; 30 | import springfox.documentation.service.ResponseMessage; 31 | 32 | /** 33 | * @author eko.zhan 34 | * @date 2018年9月2日 下午2:00:44 35 | * @version 1.0 36 | */ 37 | @Slf4j 38 | @RestController 39 | @RequestMapping("/watermark") 40 | public class WatermarkController extends BaseController { 41 | 42 | @Autowired 43 | WatermarkService watermarkService; 44 | 45 | /** 46 | * 输出文件demo https://o7planning.org/en/11765/spring-boot-file-download-example 47 | * @author eko.zhan at 2018年9月2日 下午4:26:10 48 | * @param file 49 | * @param text 50 | * @param color 51 | * @return 52 | * @throws IOException 53 | */ 54 | @ApiOperation(value="传入文件并返回水印文件", response=ResponseMessage.class) 55 | @ApiImplicitParams({ 56 | @ApiImplicitParam(name="file", value="待添加水印的文件", dataType="__file", required=true, paramType="form"), 57 | @ApiImplicitParam(name="text", value="水印内容", dataType="string", required=false, paramType="form"), 58 | @ApiImplicitParam(name="color", value="颜色码,以#开头", dataType="string", required=false, paramType="form") 59 | }) 60 | @PostMapping("/handle") 61 | public ResponseEntity handle(@RequestParam("file") MultipartFile file, @RequestParam(value="text", required=false) String text, @RequestParam(value="color", required=false) String color) throws IOException { 62 | if (!file.getOriginalFilename().toLowerCase().endsWith(".docx")) { 63 | log.error("上传的文件必须是 docx 类型"); 64 | } 65 | File dir = ResourceUtils.getFile("classpath:static/DATAS"); 66 | String pardir = DateFormatUtils.format(new Date(), "yyyyMMdd"); 67 | String filename = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss") + "." + FilenameUtils.getExtension(file.getOriginalFilename()); 68 | File originFile = new File(dir + "/" + pardir + "/" + filename); 69 | FileUtils.copyInputStreamToFile(file.getInputStream(), originFile); 70 | byte[] bytes = watermarkService.handle(originFile, text, color); 71 | ByteArrayResource resource = new ByteArrayResource(bytes); 72 | return ResponseEntity.ok() 73 | // Content-Disposition 74 | .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + originFile.getName()) 75 | // Content-Type 76 | .contentType(getMediaType(originFile.getName())) 77 | // Contet-Length 78 | .contentLength(bytes.length) 79 | .body(resource); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/java/org/artofsolving/jodconverter/document/DefaultDocumentFormatRegistry.java: -------------------------------------------------------------------------------- 1 | // 2 | // JODConverter - Java OpenDocument Converter 3 | // Copyright 2004-2012 Mirko Nasato and contributors 4 | // 5 | // JODConverter is Open Source software, you can redistribute it and/or 6 | // modify it under either (at your option) of the following licenses 7 | // 8 | // 1. The GNU Lesser General Public License v3 (or later) 9 | // -> http://www.gnu.org/licenses/lgpl-3.0.txt 10 | // 2. The Apache License, Version 2.0 11 | // -> http://www.apache.org/licenses/LICENSE-2.0.txt 12 | // 13 | package org.artofsolving.jodconverter.document; 14 | 15 | import java.util.Collections; 16 | import java.util.LinkedHashMap; 17 | import java.util.Map; 18 | 19 | public class DefaultDocumentFormatRegistry extends SimpleDocumentFormatRegistry { 20 | 21 | public DefaultDocumentFormatRegistry() { 22 | DocumentFormat pdf = new DocumentFormat("Portable Document Format", "pdf", "application/pdf"); 23 | pdf.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "writer_pdf_Export")); 24 | pdf.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "calc_pdf_Export")); 25 | pdf.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_pdf_Export")); 26 | pdf.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_pdf_Export")); 27 | addFormat(pdf); 28 | 29 | DocumentFormat swf = new DocumentFormat("Macromedia Flash", "swf", "application/x-shockwave-flash"); 30 | swf.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_flash_Export")); 31 | swf.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_flash_Export")); 32 | addFormat(swf); 33 | 34 | // disabled because it's not always available 35 | //DocumentFormat xhtml = new DocumentFormat("XHTML", "xhtml", "application/xhtml+xml"); 36 | //xhtml.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "XHTML Writer File")); 37 | //xhtml.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "XHTML Calc File")); 38 | //xhtml.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "XHTML Impress File")); 39 | //addFormat(xhtml); 40 | 41 | DocumentFormat html = new DocumentFormat("HTML", "html", "text/html"); 42 | // HTML is treated as Text when supplied as input, but as an output it is also 43 | // available for exporting Spreadsheet and Presentation formats 44 | html.setInputFamily(DocumentFamily.TEXT); 45 | html.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "HTML (StarWriter)")); 46 | html.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "HTML (StarCalc)")); 47 | html.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress_html_Export")); 48 | addFormat(html); 49 | 50 | DocumentFormat odt = new DocumentFormat("OpenDocument Text", "odt", "application/vnd.oasis.opendocument.text"); 51 | odt.setInputFamily(DocumentFamily.TEXT); 52 | odt.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "writer8")); 53 | addFormat(odt); 54 | 55 | DocumentFormat sxw = new DocumentFormat("OpenOffice.org 1.0 Text Document", "sxw", "application/vnd.sun.xml.writer"); 56 | sxw.setInputFamily(DocumentFamily.TEXT); 57 | sxw.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "StarOffice XML (Writer)")); 58 | addFormat(sxw); 59 | 60 | DocumentFormat doc = new DocumentFormat("Microsoft Word", "doc", "application/msword"); 61 | doc.setInputFamily(DocumentFamily.TEXT); 62 | doc.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "MS Word 97")); 63 | addFormat(doc); 64 | 65 | DocumentFormat docx = new DocumentFormat("Microsoft Word 2007 XML", "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"); 66 | docx.setInputFamily(DocumentFamily.TEXT); 67 | docx.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "MS Word 2007 XML")); 68 | addFormat(docx); 69 | 70 | DocumentFormat rtf = new DocumentFormat("Rich Text Format", "rtf", "text/rtf"); 71 | rtf.setInputFamily(DocumentFamily.TEXT); 72 | rtf.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "Rich Text Format")); 73 | addFormat(rtf); 74 | 75 | DocumentFormat wpd = new DocumentFormat("WordPerfect", "wpd", "application/wordperfect"); 76 | wpd.setInputFamily(DocumentFamily.TEXT); 77 | addFormat(wpd); 78 | 79 | DocumentFormat txt = new DocumentFormat("Plain Text", "txt", "text/plain"); 80 | txt.setInputFamily(DocumentFamily.TEXT); 81 | Map txtLoadAndStoreProperties = new LinkedHashMap(); 82 | txtLoadAndStoreProperties.put("FilterName", "Text (encoded)"); 83 | txtLoadAndStoreProperties.put("FilterOptions", "utf8"); 84 | txt.setLoadProperties(txtLoadAndStoreProperties); 85 | txt.setStoreProperties(DocumentFamily.TEXT, txtLoadAndStoreProperties); 86 | addFormat(txt); 87 | 88 | DocumentFormat wikitext = new DocumentFormat("MediaWiki wikitext", "wiki", "text/x-wiki"); 89 | wikitext.setStoreProperties(DocumentFamily.TEXT, Collections.singletonMap("FilterName", "MediaWiki")); 90 | //addFormat(wikitext); 91 | 92 | DocumentFormat ods = new DocumentFormat("OpenDocument Spreadsheet", "ods", "application/vnd.oasis.opendocument.spreadsheet"); 93 | ods.setInputFamily(DocumentFamily.SPREADSHEET); 94 | ods.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "calc8")); 95 | addFormat(ods); 96 | 97 | DocumentFormat sxc = new DocumentFormat("OpenOffice.org 1.0 Spreadsheet", "sxc", "application/vnd.sun.xml.calc"); 98 | sxc.setInputFamily(DocumentFamily.SPREADSHEET); 99 | sxc.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "StarOffice XML (Calc)")); 100 | addFormat(sxc); 101 | 102 | DocumentFormat xls = new DocumentFormat("Microsoft Excel", "xls", "application/vnd.ms-excel"); 103 | xls.setInputFamily(DocumentFamily.SPREADSHEET); 104 | xls.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "MS Excel 97")); 105 | addFormat(xls); 106 | 107 | DocumentFormat xlsx = new DocumentFormat("Microsoft Excel 2007 XML", "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); 108 | xlsx.setInputFamily(DocumentFamily.SPREADSHEET); 109 | xlsx.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "MS Excel 2007 XML")); 110 | addFormat(xlsx); 111 | 112 | DocumentFormat csv = new DocumentFormat("Comma Separated Values", "csv", "text/csv"); 113 | csv.setInputFamily(DocumentFamily.SPREADSHEET); 114 | Map csvLoadAndStoreProperties = new LinkedHashMap(); 115 | csvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)"); 116 | csvLoadAndStoreProperties.put("FilterOptions", "44,34,0"); // Field Separator: ','; Text Delimiter: '"' 117 | csv.setLoadProperties(csvLoadAndStoreProperties); 118 | csv.setStoreProperties(DocumentFamily.SPREADSHEET, csvLoadAndStoreProperties); 119 | addFormat(csv); 120 | 121 | DocumentFormat tsv = new DocumentFormat("Tab Separated Values", "tsv", "text/tab-separated-values"); 122 | tsv.setInputFamily(DocumentFamily.SPREADSHEET); 123 | Map tsvLoadAndStoreProperties = new LinkedHashMap(); 124 | tsvLoadAndStoreProperties.put("FilterName", "Text - txt - csv (StarCalc)"); 125 | tsvLoadAndStoreProperties.put("FilterOptions", "9,34,0"); // Field Separator: '\t'; Text Delimiter: '"' 126 | tsv.setLoadProperties(tsvLoadAndStoreProperties); 127 | tsv.setStoreProperties(DocumentFamily.SPREADSHEET, tsvLoadAndStoreProperties); 128 | addFormat(tsv); 129 | 130 | DocumentFormat odp = new DocumentFormat("OpenDocument Presentation", "odp", "application/vnd.oasis.opendocument.presentation"); 131 | odp.setInputFamily(DocumentFamily.PRESENTATION); 132 | odp.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "impress8")); 133 | addFormat(odp); 134 | 135 | DocumentFormat sxi = new DocumentFormat("OpenOffice.org 1.0 Presentation", "sxi", "application/vnd.sun.xml.impress"); 136 | sxi.setInputFamily(DocumentFamily.PRESENTATION); 137 | sxi.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "StarOffice XML (Impress)")); 138 | addFormat(sxi); 139 | 140 | DocumentFormat ppt = new DocumentFormat("Microsoft PowerPoint", "ppt", "application/vnd.ms-powerpoint"); 141 | ppt.setInputFamily(DocumentFamily.PRESENTATION); 142 | ppt.setStoreProperties(DocumentFamily.PRESENTATION, Collections.singletonMap("FilterName", "MS PowerPoint 97")); 143 | addFormat(ppt); 144 | 145 | DocumentFormat pptx = new DocumentFormat("Microsoft PowerPoint 2007 XML", "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"); 146 | pptx.setInputFamily(DocumentFamily.PRESENTATION); 147 | pptx.setStoreProperties(DocumentFamily.SPREADSHEET, Collections.singletonMap("FilterName", "MS PowerPoint 2007 XML")); 148 | addFormat(pptx); 149 | 150 | DocumentFormat odg = new DocumentFormat("OpenDocument Drawing", "odg", "application/vnd.oasis.opendocument.graphics"); 151 | odg.setInputFamily(DocumentFamily.DRAWING); 152 | odg.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw8")); 153 | addFormat(odg); 154 | 155 | DocumentFormat svg = new DocumentFormat("Scalable Vector Graphics", "svg", "image/svg+xml"); 156 | svg.setStoreProperties(DocumentFamily.DRAWING, Collections.singletonMap("FilterName", "draw_svg_Export")); 157 | addFormat(svg); 158 | } 159 | 160 | } 161 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | server.servlet.context-path=/ 3 | 4 | spring.servlet.multipart.max-file-size=50MB 5 | spring.servlet.multipart.max-request-size=50MB 6 | 7 | spring.devtools.restart.additional-exclude=application.properties 8 | 9 | ######################################################## 10 | ###THYMELEAF (ThymeleafAutoConfiguration) 11 | ######################################################## 12 | spring.thymeleaf.prefix=classpath:/templates/ 13 | spring.thymeleaf.suffix=.html 14 | spring.thymeleaf.mode=HTML 15 | spring.thymeleaf.encoding=UTF-8 16 | spring.thymeleaf.servlet.content-type=text/html 17 | spring.thymeleaf.cache=false 18 | 19 | ######################################################### 20 | ### OPENOFFICE (OpenOfficeAutoConfiguration) 21 | ######################################################### 22 | #office.port=8100,8101,8102 23 | office.port=8100 24 | office.home=D:/Programs/LibreOffice 25 | #office.home=D:/Program Files/OpenOffice 26 | office.profile= 27 | office.fileSizeMax=5242880 28 | ######################################################### 29 | ### logback 30 | ######################################################### 31 | logging.level.root=INFO 32 | logging.level.com.eastrobot=DEBUG 33 | logging.level.org.springframework=ERROR 34 | logging.level.org.hibernate=ERROR 35 | logging.level.org.apache=ERROR 36 | ######################################################### 37 | api.token=ekozhan 38 | ######################################################### 39 | 40 | # \u9A71\u52A8\u540D\u79F0 41 | spring.datasource.driver-class-name=org.sqlite.JDBC 42 | # \u6570\u636E\u5E93\u5730\u5740 43 | spring.datasource.url=jdbc:sqlite:ibothub.db 44 | # \u663E\u793A\u6570\u636E\u5E93\u64CD\u4F5C\u8BB0\u5F55 45 | spring.jpa.show-sql=true 46 | # \u6BCF\u6B21\u542F\u52A8\u66F4\u6539\u6570\u636E\u8868\u7ED3\u6784 47 | spring.jpa.hibernate.ddl-auto=update -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/DATAS/README.txt: -------------------------------------------------------------------------------- 1 | default catalog for attachment uploaded. -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/css/contents.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved. 3 | For licensing, see LICENSE.md or http://ckeditor.com/license 4 | */ 5 | 6 | body 7 | { 8 | /* Font */ 9 | font-family: sans-serif, Arial, Verdana, "Trebuchet MS"; 10 | font-size: 12px; 11 | 12 | /* Text color */ 13 | color: #333; 14 | 15 | /* Remove the background color to make it transparent */ 16 | background-color: #fff; 17 | 18 | margin: 20px; 19 | } 20 | 21 | .cke_editable 22 | { 23 | font-size: 13px; 24 | line-height: 1.6; 25 | 26 | /* Fix for missing scrollbars with RTL texts. (#10488) */ 27 | word-wrap: break-word; 28 | } 29 | 30 | blockquote 31 | { 32 | font-style: italic; 33 | font-family: Georgia, Times, "Times New Roman", serif; 34 | padding: 2px 0; 35 | border-style: solid; 36 | border-color: #ccc; 37 | border-width: 0; 38 | } 39 | 40 | .cke_contents_ltr blockquote 41 | { 42 | padding-left: 20px; 43 | padding-right: 8px; 44 | border-left-width: 5px; 45 | } 46 | 47 | .cke_contents_rtl blockquote 48 | { 49 | padding-left: 8px; 50 | padding-right: 20px; 51 | border-right-width: 5px; 52 | } 53 | 54 | a 55 | { 56 | color: #0782C1; 57 | } 58 | 59 | ol,ul,dl 60 | { 61 | /* IE7: reset rtl list margin. (#7334) */ 62 | *margin-right: 0px; 63 | /* preserved spaces for list items with text direction other than the list. (#6249,#8049)*/ 64 | padding: 0 40px; 65 | } 66 | 67 | h1,h2,h3,h4,h5,h6 68 | { 69 | font-weight: normal; 70 | line-height: 1.2; 71 | } 72 | 73 | hr 74 | { 75 | border: 0px; 76 | border-top: 1px solid #ccc; 77 | } 78 | 79 | img.right 80 | { 81 | border: 1px solid #ccc; 82 | float: right; 83 | margin-left: 15px; 84 | padding: 5px; 85 | } 86 | 87 | img.left 88 | { 89 | border: 1px solid #ccc; 90 | float: left; 91 | margin-right: 15px; 92 | padding: 5px; 93 | } 94 | 95 | pre 96 | { 97 | white-space: pre-wrap; /* CSS 2.1 */ 98 | word-wrap: break-word; /* IE7 */ 99 | -moz-tab-size: 4; 100 | tab-size: 4; 101 | } 102 | 103 | .marker 104 | { 105 | background-color: Yellow; 106 | } 107 | 108 | span[lang] 109 | { 110 | font-style: italic; 111 | } 112 | 113 | figure 114 | { 115 | text-align: center; 116 | border: solid 1px #ccc; 117 | border-radius: 2px; 118 | background: rgba(0,0,0,0.05); 119 | padding: 10px; 120 | margin: 10px 20px; 121 | display: inline-block; 122 | } 123 | 124 | figure > figcaption 125 | { 126 | text-align: center; 127 | display: block; /* For IE8 */ 128 | } 129 | 130 | a > img { 131 | padding: 1px; 132 | margin: 1px; 133 | border: none; 134 | outline: 1px solid #0782C1; 135 | } 136 | 137 | /* Widget Styles */ 138 | .code-featured 139 | { 140 | border: 5px solid red; 141 | } 142 | 143 | .math-featured 144 | { 145 | padding: 20px; 146 | box-shadow: 0 0 2px rgba(200, 0, 0, 1); 147 | background-color: rgba(255, 0, 0, 0.05); 148 | margin: 10px; 149 | } 150 | 151 | .image-clean 152 | { 153 | border: 0; 154 | background: none; 155 | padding: 0; 156 | } 157 | 158 | .image-clean > figcaption 159 | { 160 | font-size: .9em; 161 | text-align: right; 162 | } 163 | 164 | .image-grayscale 165 | { 166 | background-color: white; 167 | color: #666; 168 | } 169 | 170 | .image-grayscale img, img.image-grayscale 171 | { 172 | filter: grayscale(100%); 173 | } 174 | 175 | .embed-240p 176 | { 177 | max-width: 426px; 178 | max-height: 240px; 179 | margin:0 auto; 180 | } 181 | 182 | .embed-360p 183 | { 184 | max-width: 640px; 185 | max-height: 360px; 186 | margin:0 auto; 187 | } 188 | 189 | .embed-480p 190 | { 191 | max-width: 854px; 192 | max-height: 480px; 193 | margin:0 auto; 194 | } 195 | 196 | .embed-720p 197 | { 198 | max-width: 1280px; 199 | max-height: 720px; 200 | margin:0 auto; 201 | } 202 | 203 | .embed-1080p 204 | { 205 | max-width: 1920px; 206 | max-height: 1080px; 207 | margin:0 auto; 208 | } -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/css/pastefromword.css: -------------------------------------------------------------------------------- 1 | body.document-editor { 2 | width: 15.8cm; 3 | min-height: 21cm; 4 | padding: 1cm 2cm 2cm; 5 | margin: 0.5cm auto; 6 | border: 1px #D3D3D3 solid; 7 | border-radius: 5px; 8 | background: white; 9 | box-shadow: 0 0 5px rgba(0, 0, 0, 0.1); 10 | } 11 | 12 | body.document-editor, body.document-editor td, body.document-editor th { 13 | font-size: 0.9em; 14 | border: 1px solid #d3d3d3 !important; 15 | } 16 | 17 | body.document-editor table { 18 | margin-top: 0.5cm; 19 | border:1px solid #d3d3d3 !important; 20 | border-spacing: 1px !important; 21 | } 22 | 23 | body.document-editor table td > p { 24 | margin-top: 0; 25 | margin-bottom: 0; 26 | padding: 4px 0 3px 5px; 27 | } 28 | 29 | body.document-editor h1 { 30 | margin-bottom: 1cm; 31 | } 32 | 33 | body.document-editor ol, body.document-editor ul, body.document-editor dl { 34 | padding: 0 20px; 35 | } 36 | 37 | body.document-editor p { 38 | margin-top: 0; 39 | margin-bottom: 6px; 40 | line-height: 1.4; 41 | } -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/css/style.css: -------------------------------------------------------------------------------- 1 | body{ 2 | margin: 3px; 3 | font-size: 12px; 4 | } -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/img/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekoz/kbase-doc/33995dc4dc79d434ebb58255d997c27b5d014492/kbase-doc-alpha/src/main/resources/static/img/edit.png -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/img/list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekoz/kbase-doc/33995dc4dc79d434ebb58255d997c27b5d014492/kbase-doc-alpha/src/main/resources/static/img/list.png -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/img/read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekoz/kbase-doc/33995dc4dc79d434ebb58255d997c27b5d014492/kbase-doc-alpha/src/main/resources/static/img/read.png -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/img/upload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ekoz/kbase-doc/33995dc4dc79d434ebb58255d997c27b5d014492/kbase-doc-alpha/src/main/resources/static/img/upload.png -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/js/edit.js: -------------------------------------------------------------------------------- 1 | var config = { 2 | // Define the toolbar: http://docs.ckeditor.com/#!/guide/dev_toolbar 3 | // The full preset from CDN which we used as a base provides more features than we need. 4 | // Also by default it comes with a 3-line toolbar. Here we put all buttons in two rows. 5 | toolbar: [ 6 | { name: 'clipboard', items: [ 'PasteFromWord', '-', 'Undo', 'Redo' ] }, 7 | { name: 'basicstyles', items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'RemoveFormat', 'Subscript', 'Superscript' ] }, 8 | { name: 'links', items: [ 'Link', 'Unlink' ] }, 9 | { name: 'paragraph', items: [ 'NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote' ] }, 10 | { name: 'insert', items: [ 'Image', 'Table' ] }, 11 | { name: 'editing', items: [ 'Scayt' ] }, 12 | '/', 13 | 14 | { name: 'styles', items: [ 'Format', 'Font', 'FontSize' ] }, 15 | { name: 'colors', items: [ 'TextColor', 'BGColor', 'CopyFormatting' ] }, 16 | { name: 'align', items: [ 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock' ] }, 17 | { name: 'document', items: [ 'Print', 'Source' ] } 18 | ], 19 | 20 | // Since we define all configuration options here, let's instruct CKEditor to not load config.js which it does by default. 21 | // One HTTP request less will result in a faster startup time. 22 | // For more information check http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-customConfig 23 | customConfig: '', 24 | 25 | // Upload images to a CKFinder connector (note that the response type is set to JSON). 26 | // uploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json', 27 | 28 | // Configure your file manager integration. This example uses CKFinder 3 for PHP. 29 | // filebrowserBrowseUrl: '/ckfinder/ckfinder.html', 30 | // filebrowserImageBrowseUrl: '/ckfinder/ckfinder.html?type=Images', 31 | // filebrowserUploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files', 32 | // filebrowserImageUploadUrl: '/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images', 33 | 34 | // Sometimes applications that convert HTML to PDF prefer setting image width through attributes instead of CSS styles. 35 | // For more information check: 36 | // - About Advanced Content Filter: http://docs.ckeditor.com/#!/guide/dev_advanced_content_filter 37 | // - About Disallowed Content: http://docs.ckeditor.com/#!/guide/dev_disallowed_content 38 | // - About Allowed Content: http://docs.ckeditor.com/#!/guide/dev_allowed_content_rules 39 | disallowedContent: 'img{width,height,float}', 40 | extraAllowedContent: 'img[width,height,align];span{background}', 41 | 42 | // Enabling extra plugins, available in the full-all preset: http://ckeditor.com/presets-all 43 | extraPlugins: 'colorbutton,font,justify,print,tableresize,uploadimage,uploadfile,pastefromword,liststyle', 44 | 45 | /*********************** File management support ***********************/ 46 | // In order to turn on support for file uploads, CKEditor has to be configured to use some server side 47 | // solution with file upload/management capabilities, like for example CKFinder. 48 | // For more information see http://docs.ckeditor.com/#!/guide/dev_ckfinder_integration 49 | 50 | // Uncomment and correct these lines after you setup your local CKFinder instance. 51 | // filebrowserBrowseUrl: 'http://example.com/ckfinder/ckfinder.html', 52 | // filebrowserUploadUrl: 'http://example.com/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Files', 53 | /*********************** File management support ***********************/ 54 | 55 | // Make the editing area bigger than default. 56 | height: 480, 57 | width: 940, 58 | 59 | // An array of stylesheets to style the WYSIWYG area. 60 | // Note: it is recommended to keep your own styles in a separate file in order to make future updates painless. 61 | contentsCss: [ $.kbase.ctx + '/css/contents.css', $.kbase.ctx + '/css/pastefromword.css' ], 62 | 63 | // This is optional, but will let us define multiple different styles for multiple editors using the same CSS file. 64 | bodyClass: 'document-editor', 65 | 66 | // Reduce the list of block elements listed in the Format dropdown to the most commonly used. 67 | format_tags: 'p;h1;h2;h3;pre', 68 | 69 | // Simplify the Image and Link dialog windows. The "Advanced" tab is not needed in most cases. 70 | removeDialogTabs: 'image:advanced;link:advanced', 71 | 72 | // Define the list of styles which should be available in the Styles dropdown list. 73 | // If the "class" attribute is used to style an element, make sure to define the style for the class in "mystyles.css" 74 | // (and on your website so that it rendered in the same way). 75 | // Note: by default CKEditor looks for styles.js file. Defining stylesSet inline (as below) stops CKEditor from loading 76 | // that file, which means one HTTP request less (and a faster startup). 77 | // For more information see http://docs.ckeditor.com/#!/guide/dev_styles 78 | stylesSet: [ 79 | /* Inline Styles */ 80 | { name: 'Marker', element: 'span', attributes: { 'class': 'marker' } }, 81 | { name: 'Cited Work', element: 'cite' }, 82 | { name: 'Inline Quotation', element: 'q' }, 83 | 84 | /* Object Styles */ 85 | { 86 | name: 'Special Container', 87 | element: 'div', 88 | styles: { 89 | padding: '5px 10px', 90 | background: '#eee', 91 | border: '1px solid #ccc' 92 | } 93 | }, 94 | { 95 | name: 'Compact table', 96 | element: 'table', 97 | attributes: { 98 | cellpadding: '5', 99 | cellspacing: '0', 100 | border: '1', 101 | bordercolor: '#ccc' 102 | }, 103 | styles: { 104 | 'border-collapse': 'collapse' 105 | } 106 | }, 107 | { name: 'Borderless Table', element: 'table', styles: { 'border-style': 'hidden', 'background-color': '#E6E6FA' } }, 108 | { name: 'Square Bulleted List', element: 'ul', styles: { 'list-style-type': 'square' } } 109 | ] 110 | }; 111 | $.post($.kbase.ctx + '/index/loadFileData', {id: $('#id').val()}, function(data){ 112 | CKEDITOR.replace( 'docEditor', config ); 113 | //CKEDITOR.instances.docEditor.setData(data); 114 | 115 | CKEDITOR.on('instanceReady', function (event) { 116 | var editor = event.editor; 117 | editor.setData(data); 118 | editor.setReadOnly(true); 119 | 120 | window.setTimeout(function(){ 121 | var imgList = $($('iframe')[0].contentWindow.document).find('img'); 122 | $(imgList).each(function(i, img){ 123 | var _url = $(img).attr('src'); 124 | if (_url.indexOf('http')==-1){ 125 | $(img).attr('src', $.kbase.ctx + '/index/loadFileImg?id=' + $('#id').val() + '&imgname=' + $(img).attr('src')); 126 | } 127 | }); 128 | }, 100); 129 | }); 130 | 131 | }, 'text'); 132 | 133 | $('#btnModify').show(); 134 | $('#btnDelete').show(); 135 | $('#btnDownload').show(); 136 | 137 | //修改 和 保存 138 | $('#btnModify').click(function(){ 139 | var status = $(this).attr('_status'); 140 | if (status==0){ 141 | //修改 142 | CKEDITOR.instances.docEditor.setReadOnly(false); 143 | $(this).text('保存'); 144 | $(this).attr('_status', 1); 145 | $('#btnSaveAsVersion').show(); 146 | }else{ 147 | //保存 148 | if (window.confirm('确认保存修改吗')){ 149 | var data = CKEDITOR.instances.docEditor.getData(); 150 | $.post($.kbase.ctx + '/index/saveFileData', {id: $('#id').val(), data: data}, function(data){ 151 | if (data.result==1){ 152 | alert('保存成功'); 153 | } 154 | }, 'json'); 155 | } 156 | } 157 | }); 158 | 159 | //保存为版本 160 | $('#btnSaveAsVersion').click(function(){ 161 | alert('请填写版本信息'); 162 | }); -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/js/index.js: -------------------------------------------------------------------------------- 1 | function loadData(){ 2 | $.post($.kbase.ctx + '/index/getDataList', function(data){ 3 | $('#list').html(template('templateList', data)); 4 | }, 'json'); 5 | }; 6 | 7 | loadData(); 8 | 9 | $('#list').on('click', 'a', function(){ 10 | location.href = $.kbase.ctx + '/edit?id=' + $(this).attr('_id'); 11 | }); 12 | 13 | $('#list').on('click', '.btn-danger', function(){ 14 | var id = $(this).parents('tr').find('td:eq(0) a').attr('_id'); 15 | if (window.confirm('确认删除吗')){ 16 | axios.delete($.kbase.ctx + '/index/' + id) 17 | .then(()=>{ 18 | loadData(); 19 | }); 20 | } 21 | }); -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/static/js/upload.js: -------------------------------------------------------------------------------- 1 | var uploader = new ss.SimpleUpload({ 2 | button: 'btnUpload', // HTML element used as upload button 3 | url: $.kbase.ctx + '/index/uploadData', // URL of server-side upload handler 4 | name: 'uploadFile', // Parameter name of the uploaded file 5 | responseType: 'json', 6 | onSubmit: function (filename, extension) { 7 | this.setFileSizeBox($('#sizeBox')[0]); // designate this element as file size container 8 | this.setProgressBar($('#progress')[0]); // designate as progress bar 9 | }, 10 | onComplete: function(filename, response, uploadBtn, fileSize){ 11 | if (!response) { 12 | alert(filename + ' 上传失败'); 13 | return false; 14 | } 15 | alert(filename + ' 上传成功'); 16 | location.href = $.kbase.ctx; 17 | } 18 | }); -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/templates/body.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
7 |
8 | 上传文件 9 | 文件列表 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/templates/edit.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 29 |
30 |
31 | 32 | 33 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 30 |
文件名称文件路径文件大小 
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/templates/script.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 28 | 29 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/main/resources/templates/upload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/KbaseDocApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class KbaseDocApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/dao/AttachmentRepositoryTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.eastrobot.doc.dao; 5 | 6 | import javax.annotation.Resource; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.boot.test.context.SpringBootTest; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | 12 | /** 13 | * @author eko.zhan 14 | * @version v1.0 15 | * @date 2022/10/20 19:45 16 | */ 17 | @RunWith(SpringRunner.class) 18 | @SpringBootTest 19 | public class AttachmentRepositoryTests { 20 | 21 | @Resource 22 | AttachmentRepository attachmentRepository; 23 | 24 | @Test 25 | public void testFindAll(){ 26 | attachmentRepository.findAll() 27 | .forEach(attachment -> System.out.println(attachment)); 28 | } 29 | 30 | @Test 31 | public void testFindById(){ 32 | System.out.println(attachmentRepository.findById(1L)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/demo/Tests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Powered by http://ibotstat.com 3 | */ 4 | package com.eastrobot.doc.demo; 5 | 6 | import org.apache.commons.io.FileUtils; 7 | import org.apache.poi.ss.usermodel.CellType; 8 | import org.apache.poi.ss.usermodel.Row; 9 | import org.apache.poi.ss.usermodel.Sheet; 10 | import org.apache.poi.ss.usermodel.Workbook; 11 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 12 | import org.junit.Test; 13 | 14 | import java.io.File; 15 | import java.io.FileOutputStream; 16 | import java.io.IOException; 17 | import java.io.OutputStream; 18 | import java.util.Calendar; 19 | import java.util.Date; 20 | import java.util.List; 21 | 22 | /** 23 | * @author eko.zhan 24 | * @version v1.0 25 | * @date 2019/12/30 13:12 26 | */ 27 | public class Tests { 28 | 29 | @Test 30 | public void test() throws IOException { 31 | Workbook wb = new XSSFWorkbook(); 32 | Sheet sheet = wb.createSheet("会计考试"); 33 | addTitle(sheet); 34 | 35 | List list = FileUtils.readLines(new File("E:\\会计成绩名单.txt"), "UTF-8"); 36 | int i=0; 37 | for (String line : list){ 38 | if (line.contains("麻城")){ 39 | line = line.substring(1, line.length()-1).replace("\"", ""); 40 | System.out.println(line); 41 | String[] arr = line.split(","); 42 | i++; 43 | Row row = sheet.createRow(i); 44 | row.createCell(0).setCellValue(arr[0]); 45 | row.createCell(1).setCellValue(arr[1]); 46 | row.createCell(2).setCellValue(arr[2]); 47 | row.createCell(3).setCellValue(arr[3]); 48 | row.createCell(4).setCellValue(arr[4]); 49 | row.createCell(5).setCellValue(arr[5]); 50 | row.createCell(6).setCellValue(arr[6]); 51 | row.createCell(7).setCellValue(arr[7]); 52 | row.createCell(8).setCellValue(arr[8]); 53 | row.createCell(9).setCellValue(arr[9]); 54 | } 55 | } 56 | System.out.println(i); 57 | //============================================================== 58 | 59 | 60 | try (OutputStream fileOut = new FileOutputStream("E://workbook.xlsx")) { 61 | wb.write(fileOut); 62 | } 63 | } 64 | 65 | private void addTitle(Sheet sheet){ 66 | Row row = sheet.createRow(0); 67 | row.createCell(0).setCellValue("专业名称"); 68 | row.createCell(1).setCellValue("考号"); 69 | row.createCell(2).setCellValue("学生姓名"); 70 | row.createCell(3).setCellValue("学校名称"); 71 | row.createCell(4).setCellValue("总分"); 72 | row.createCell(5).setCellValue("全省排名"); 73 | row.createCell(6).setCellValue("全省最高分"); 74 | row.createCell(7).setCellValue("全省平均分"); 75 | row.createCell(8).setCellValue("学校平均分"); 76 | row.createCell(9).setCellValue("全省参考人数"); 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/samples/BackgroundImage.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc.samples; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import javax.xml.bind.JAXBElement; 7 | 8 | import org.docx4j.jaxb.Context; 9 | import org.docx4j.openpackaging.packages.WordprocessingMLPackage; 10 | import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage; 11 | import org.docx4j.vml.CTFill; 12 | import org.docx4j.wml.CTBackground; 13 | import org.docx4j.wml.ObjectFactory; 14 | 15 | /* 16 | * 17 | * Add w:document/w:background; note that this is only visible in Windows Explorer file preview, or 18 | * Word's "Web layout" and "Full screen reading" document views (ie not Print Layout, Outline, 19 | * or Draft). Checking Word options > Display > Printing options > Print background colors and images 20 | * makes no difference to what you see in Print Layout, but it does change what you see in Print Preview. 21 | * 22 | * This is different to a watermark, which is set via the headers (see WatermarkPicture sample for that), 23 | * which is probably what you want. 24 | * 25 | * From [MS-OI29500]: 26 | * 27 | * a. The standard states that any element from the VML namespace or the drawingML namespace 28 | * is allowed as a child of the background element. 29 | * 30 | * Word renders any drawingML specified as a background at the beginning of the document and not as a background. 31 | */ 32 | public class BackgroundImage { 33 | 34 | 35 | static String DOCX_OUT; 36 | 37 | public static void main(String[] args) throws Exception 38 | { 39 | 40 | // The image to add 41 | imageFile = new File("E:\\ConvertTester\\images\\jshrss-logo.png" ); 42 | 43 | // Save it to 44 | DOCX_OUT = "E:\\ConvertTester\\docx/OUT_BackgroundImage.docx"; 45 | 46 | BackgroundImage sample = new BackgroundImage(); 47 | sample.addBackground(); 48 | } 49 | 50 | static ObjectFactory factory = Context.getWmlObjectFactory(); 51 | static File imageFile; 52 | 53 | private byte[] image; 54 | private WordprocessingMLPackage wordMLPackage; 55 | 56 | public void addBackground() throws Exception 57 | { 58 | 59 | image = this.getImage(); 60 | 61 | System.out.println("ekozhan" + image.length); 62 | 63 | wordMLPackage = WordprocessingMLPackage.createPackage(); 64 | 65 | BinaryPartAbstractImage imagePartBG = BinaryPartAbstractImage.createImagePart(wordMLPackage, image); 66 | 67 | wordMLPackage.getMainDocumentPart().getJaxbElement().setBackground( 68 | createBackground( 69 | imagePartBG.getRelLast().getId())); 70 | 71 | wordMLPackage.getMainDocumentPart().addParagraphOfText("Ekozhan"); 72 | 73 | File f = new File(DOCX_OUT); 74 | wordMLPackage.save(f); 75 | 76 | } 77 | 78 | private static CTBackground createBackground(String rId) { 79 | 80 | org.docx4j.wml.ObjectFactory wmlObjectFactory = new org.docx4j.wml.ObjectFactory(); 81 | 82 | CTBackground background = wmlObjectFactory.createCTBackground(); 83 | background.setColor("FF0000"); 84 | org.docx4j.vml.ObjectFactory vmlObjectFactory = new org.docx4j.vml.ObjectFactory(); 85 | // Create object for background (wrapped in JAXBElement) 86 | org.docx4j.vml.CTBackground background2 = vmlObjectFactory 87 | .createCTBackground(); 88 | JAXBElement backgroundWrapped = vmlObjectFactory 89 | .createBackground(background2); 90 | background.getAnyAndAny().add(backgroundWrapped); 91 | background2.setTargetscreensize("1024,768"); 92 | background2.setVmlId("_x0000_s1025"); 93 | background2.setBwmode(org.docx4j.vml.officedrawing.STBWMode.LIGHT_GRAYSCALE); 94 | // Create object for fill 95 | CTFill fill = vmlObjectFactory.createCTFill(); 96 | background2.setFill(fill); 97 | fill.setTitle("Alien 1"); 98 | fill.setId(rId); 99 | fill.setType(org.docx4j.vml.STFillType.FRAME); 100 | fill.setRecolor(org.docx4j.vml.STTrueFalse.T); 101 | 102 | return background; 103 | } 104 | 105 | private byte[] getImage() throws IOException { 106 | 107 | // Our utility method wants that as a byte array 108 | java.io.InputStream is = new java.io.FileInputStream(imageFile ); 109 | long length = imageFile.length(); 110 | // You cannot create an array using a long type. 111 | // It needs to be an int type. 112 | if (length > Integer.MAX_VALUE) { 113 | System.out.println("File too large!!"); 114 | } 115 | byte[] bytes = new byte[(int)length]; 116 | int offset = 0; 117 | int numRead = 0; 118 | while (offset < bytes.length 119 | && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { 120 | offset += numRead; 121 | } 122 | // Ensure all the bytes have been read in 123 | if (offset < bytes.length) { 124 | System.out.println("Could not completely read file "+imageFile.getName()); 125 | } 126 | is.close(); 127 | 128 | return bytes; 129 | } 130 | 131 | 132 | } 133 | 134 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/samples/WatermarkExcelPicture.java: -------------------------------------------------------------------------------- 1 | package com.eastrobot.doc.samples; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | import org.apache.commons.io.FileUtils; 7 | import org.docx4j.openpackaging.packages.SpreadsheetMLPackage; 8 | import org.docx4j.openpackaging.parts.SpreadsheetML.WorksheetPart; 9 | import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage; 10 | import org.docx4j.relationships.Relationship; 11 | import org.xlsx4j.sml.CTSheetBackgroundPicture; 12 | 13 | 14 | /** 15 | * 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 0 25 | 26 | 27 | 28 | 29 | 30 | 31 | &G 32 | 33 | 34 | 35 | 36 | * @author Administrator 37 | * 38 | */ 39 | public class WatermarkExcelPicture { 40 | 41 | // String fileName = System.getProperty("user.dir") + "/waterMarksample.xlsx"; 42 | String fileName = "E:/waterMarksample.xlsx"; 43 | // String fileName = "d:/word/print/test4.xlsx"; 44 | String waterMark = "WATER-MARK"; 45 | // String outMarkPic = System.getProperty("user.dir") + "/waterMark.png"; 46 | String outMarkPic = "E:\\\\ConvertTester\\\\images\\\\jshrss-logo.png"; 47 | 48 | public void addWatermark() throws Exception{ 49 | File f = new File("E:/提取英文名.xlsx"); 50 | SpreadsheetMLPackage pkg = SpreadsheetMLPackage.load(f); 51 | int size = pkg.getWorkbookPart().getContents().getSheets().getSheet().size(); 52 | for (int i=0;i 62 | * @param pkg 63 | * @param worksheet 64 | * @throws Exception 65 | * @throws IOException 66 | */ 67 | private void createBgPic(SpreadsheetMLPackage pkg, WorksheetPart worksheet) throws Exception, IOException { 68 | CTSheetBackgroundPicture ctSheetBackgroundPicture = org.xlsx4j.jaxb.Context.getsmlObjectFactory().createCTSheetBackgroundPicture(); 69 | worksheet.getContents().setPicture(ctSheetBackgroundPicture); 70 | 71 | BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(pkg, worksheet, FileUtils.readFileToByteArray(new File(outMarkPic))); 72 | Relationship sourceRelationship = imagePart.getSourceRelationships().get(0); 73 | String imageRelID = sourceRelationship.getId(); 74 | ctSheetBackgroundPicture.setId(imageRelID); 75 | } 76 | 77 | public static void main(String[] args) { 78 | try { 79 | new WatermarkExcelPicture().addWatermark(); 80 | } catch (Exception e) { 81 | e.printStackTrace(); 82 | } 83 | } 84 | 85 | 86 | } -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/samples/WatermarkExcelTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.samples; 5 | 6 | import java.awt.image.BufferedImage; 7 | import java.io.ByteArrayOutputStream; 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileOutputStream; 11 | import java.io.IOException; 12 | import java.io.InputStream; 13 | import java.io.OutputStream; 14 | 15 | import javax.imageio.ImageIO; 16 | 17 | import org.apache.commons.io.IOUtils; 18 | import org.apache.poi.ss.usermodel.ClientAnchor; 19 | import org.apache.poi.ss.usermodel.ClientAnchor.AnchorType; 20 | import org.apache.poi.ss.usermodel.CreationHelper; 21 | import org.apache.poi.ss.usermodel.Drawing; 22 | import org.apache.poi.ss.usermodel.Picture; 23 | import org.apache.poi.ss.usermodel.Sheet; 24 | import org.apache.poi.xssf.usermodel.XSSFClientAnchor; 25 | import org.apache.poi.xssf.usermodel.XSSFDrawing; 26 | import org.apache.poi.xssf.usermodel.XSSFFont; 27 | import org.apache.poi.xssf.usermodel.XSSFRichTextString; 28 | import org.apache.poi.xssf.usermodel.XSSFShape; 29 | import org.apache.poi.xssf.usermodel.XSSFSheet; 30 | import org.apache.poi.xssf.usermodel.XSSFTextBox; 31 | import org.apache.poi.xssf.usermodel.XSSFWorkbook; 32 | import org.junit.Test; 33 | 34 | /** 35 | * @author eko.zhan 36 | * @date 2018年9月3日 下午7:27:58 37 | * @version 1.0 38 | */ 39 | public class WatermarkExcelTests { 40 | 41 | @Test 42 | public void test1() throws IOException { 43 | 44 | ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); 45 | String imgPath = "D:\\Xiaoi\\logo\\logo.png"; 46 | BufferedImage bufferImg = ImageIO.read(new File(imgPath)); 47 | //这里要注意,第二个参数将会决定插入图片形式,如果是一个png的图片,背景透明,但是此处设置为jpg格式将会自动添加黑色背景 48 | ImageIO.write(bufferImg, "png", byteArrayOut); 49 | 50 | 51 | String filepath = "E:\\ConvertTester\\excel\\abcde.xlsx"; 52 | File originFile = new File(filepath); 53 | InputStream in = new FileInputStream(originFile); 54 | XSSFWorkbook workbook = new XSSFWorkbook(in); 55 | XSSFSheet sheet = workbook.createSheet("testSheet"); 56 | //画图的顶级管理器,一个sheet只能获取一个 57 | XSSFDrawing drawing = sheet.createDrawingPatriarch(); 58 | //anchor主要用于设置图片的属性 59 | // XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, (short) 2, 4, (short) 13, 26); 60 | /* 61 | * 参数定义: 62 | * 第一个参数是(x轴的开始节点); 63 | * 第二个参数是(是y轴的开始节点); 64 | * 第三个参数是(是x轴的结束节点); 65 | * 第四个参数是(是y轴的结束节点); 66 | * 第五个参数是(是从Excel的第几列开始插入图片,从0开始计数); 67 | * 第六个参数是(是从excel的第几行开始插入图片,从0开始计数); 68 | * 第七个参数是(图片宽度,共多少列); 69 | * 第8个参数是(图片高度,共多少行); 70 | */ 71 | XSSFClientAnchor anchor = drawing.createAnchor(0, 0, Short.MAX_VALUE, Integer.MAX_VALUE, 0, 0, 10, 10); 72 | anchor.setAnchorType(AnchorType.DONT_MOVE_DO_RESIZE); 73 | //插入图片 74 | drawing.createPicture(anchor, workbook.addPicture(byteArrayOut.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG)); 75 | workbook.write(new FileOutputStream("E:\\ConvertTester\\excel\\abcd-011.xlsx")); 76 | workbook.close(); 77 | } 78 | 79 | @Test 80 | public void test2() throws IOException { 81 | //create a new workbook 82 | XSSFWorkbook wb = new XSSFWorkbook(); //or new HSSFWorkbook(); 83 | String imgPath = "D:\\Xiaoi\\logo\\logo.png"; 84 | //add picture data to this workbook. 85 | InputStream is = new FileInputStream(imgPath); 86 | byte[] bytes = IOUtils.toByteArray(is); 87 | int pictureIdx = wb.addPicture(bytes, XSSFWorkbook.PICTURE_TYPE_PNG); 88 | is.close(); 89 | 90 | CreationHelper helper = wb.getCreationHelper(); 91 | 92 | //create sheet 93 | Sheet sheet = wb.createSheet(); 94 | 95 | // Create the drawing patriarch. This is the top level container for all shapes. 96 | Drawing drawing = sheet.createDrawingPatriarch(); 97 | 98 | //add a picture shape 99 | ClientAnchor anchor = helper.createClientAnchor(); 100 | //set top-left corner of the picture, 101 | //subsequent call of Picture#resize() will operate relative to it 102 | anchor.setCol1(3); 103 | anchor.setRow1(2); 104 | anchor.setAnchorType(AnchorType.DONT_MOVE_AND_RESIZE); 105 | Picture pict = drawing.createPicture(anchor, pictureIdx); 106 | 107 | //auto-size picture relative to its top-left corner 108 | pict.resize(); 109 | 110 | //save workbook 111 | String file = "E:\\ConvertTester\\excel\\picture.xls"; 112 | if(wb instanceof XSSFWorkbook) file += "x"; 113 | try (OutputStream fileOut = new FileOutputStream(file)) { 114 | wb.write(fileOut); 115 | } 116 | } 117 | 118 | @Test 119 | public void test3() { 120 | // String filepath = "E:\\ConvertTester\\excel\\abcde.xlsx"; 121 | // File originFile = new File(filepath); 122 | // InputStream in = new FileInputStream(originFile); 123 | // XSSFWorkbook workbook = new XSSFWorkbook(in); 124 | // XSSFSheet sheet = workbook.createSheet("testSheet"); 125 | 126 | // workbook.gets 127 | // XSLFSlideMaster slideMaster = sheet.getSlideMasters().get(0); 128 | // XSLFSlideLayout slidelayout = slideMaster.getLayout(SlideLayout.TITLE_AND_CONTENT); 129 | // XSLFPictureShape ps = slidelayout.createPicture(pd); 130 | // ps.setAnchor(new Rectangle2D.Double(100, 100, 400, 400)); 131 | 132 | } 133 | 134 | @Test 135 | public void testExcel2() throws IOException { 136 | String filepath = "E:\\ConvertTester\\excel\\abcd.xlsx"; 137 | File originFile = new File(filepath); 138 | InputStream in = new FileInputStream(originFile); 139 | XSSFWorkbook workbook = new XSSFWorkbook(in); 140 | XSSFSheet sheet = workbook.createSheet("testSheet"); 141 | 142 | XSSFDrawing drawing = sheet.createDrawingPatriarch(); 143 | 144 | XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, (short) 2, 4, (short) 13, 26); 145 | 146 | } 147 | 148 | @Test 149 | public void testExcel() throws IOException { 150 | String filepath = "E:\\ConvertTester\\excel\\abcd.xlsx"; 151 | File originFile = new File(filepath); 152 | InputStream in = new FileInputStream(originFile); 153 | XSSFWorkbook workbook = new XSSFWorkbook(in); 154 | XSSFSheet sheet = workbook.createSheet("testSheet"); 155 | 156 | XSSFDrawing drawing = sheet.createDrawingPatriarch(); 157 | 158 | XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 1023, 255, (short) 2, 4, (short) 13, 26); 159 | 160 | XSSFTextBox textbox = drawing.createTextbox(anchor); 161 | XSSFRichTextString rtxt = new XSSFRichTextString("ekozhan"); 162 | XSSFFont font = workbook.createFont(); 163 | font.setColor((short) 27); 164 | font.setBold(true); 165 | font.setFontHeightInPoints((short) 192); 166 | font.setFontName("Verdana"); 167 | rtxt.applyFont(font); 168 | textbox.setText(rtxt); 169 | // textbox.setLineStyle(XSSFShape); 170 | textbox.setNoFill(true); 171 | workbook.write(new FileOutputStream(filepath)); 172 | workbook.close(); 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/samples/WatermarkPdfTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.samples; 5 | 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.FileNotFoundException; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | 12 | import com.eastrobot.doc.util.BaseTests; 13 | import org.junit.Test; 14 | 15 | import com.itextpdf.text.DocumentException; 16 | import com.itextpdf.text.Element; 17 | import com.itextpdf.text.Font; 18 | import com.itextpdf.text.Font.FontFamily; 19 | import com.itextpdf.text.Image; 20 | import com.itextpdf.text.Phrase; 21 | import com.itextpdf.text.Rectangle; 22 | import com.itextpdf.text.pdf.ColumnText; 23 | import com.itextpdf.text.pdf.PdfContentByte; 24 | import com.itextpdf.text.pdf.PdfGState; 25 | import com.itextpdf.text.pdf.PdfReader; 26 | import com.itextpdf.text.pdf.PdfStamper; 27 | 28 | 29 | /** 30 | * @author eko.zhan 31 | * @date 2018年8月31日 下午1:41:38 32 | * @version 1.0 33 | */ 34 | public class WatermarkPdfTests extends BaseTests { 35 | 36 | /** 37 | * pdf 用文字加水印,存在问题,如何支持中文 38 | * @author eko.zhan at 2018年9月2日 下午1:44:40 39 | * @throws FileNotFoundException 40 | * @throws IOException 41 | * @throws DocumentException 42 | */ 43 | @Test 44 | public void testVisioAsPdfWithText() throws FileNotFoundException, IOException, DocumentException{ 45 | File inputFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx.vsdx"); 46 | File outputFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx_libreoffice.pdf"); 47 | if (!outputFile.exists()) { 48 | convert(inputFile, outputFile); 49 | } 50 | File destFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx_libreoffice_watermark.pdf"); 51 | //转换成 pdf 后利用 itext 加水印 52 | PdfReader reader = new PdfReader(new FileInputStream(outputFile)); 53 | PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destFile)); 54 | int pageNo = reader.getNumberOfPages(); 55 | Font f = new Font(FontFamily.HELVETICA, 28); 56 | Phrase p = new Phrase("Xiaoi Robot", f); 57 | for (int i=1;i<=pageNo;i++) { 58 | PdfContentByte over = stamper.getOverContent(i); 59 | over.saveState(); 60 | PdfGState gs1 = new PdfGState(); 61 | gs1.setFillOpacity(0.5f); 62 | over.setGState(gs1); 63 | ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, 297, 450, 0); 64 | over.restoreState(); 65 | } 66 | stamper.close(); 67 | reader.close(); 68 | } 69 | /** 70 | * pdf 用图片加水印 71 | * @author eko.zhan at 2018年9月2日 下午1:44:58 72 | * @throws FileNotFoundException 73 | * @throws IOException 74 | * @throws DocumentException 75 | */ 76 | @Test 77 | public void testVisioAsPdfWithImg() throws FileNotFoundException, IOException, DocumentException{ 78 | File inputFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx.vsdx"); 79 | File outputFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx_libreoffice.pdf"); 80 | if (!outputFile.exists()) { 81 | convert(inputFile, outputFile); 82 | } 83 | File destFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx_libreoffice_watermark.pdf"); 84 | final String IMG = "D:\\Xiaoi\\logo\\logo.png"; 85 | //转换成 pdf 后利用 itext 加水印 86 | PdfReader reader = new PdfReader(new FileInputStream(outputFile)); 87 | PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(destFile)); 88 | int pageNo = reader.getNumberOfPages(); 89 | // text watermark 90 | Font f = new Font(FontFamily.HELVETICA, 30); 91 | Phrase p = new Phrase("Xiaoi Robot Image", f); 92 | // image watermark 93 | Image img = Image.getInstance(IMG); 94 | float w = img.getScaledWidth(); 95 | float h = img.getScaledHeight(); 96 | // transparency 97 | PdfGState gs1 = new PdfGState(); 98 | gs1.setFillOpacity(0.5f); 99 | // properties 100 | PdfContentByte over; 101 | Rectangle pagesize; 102 | float x, y; 103 | // loop over every page 104 | for (int i = 1; i <= pageNo; i++) { 105 | pagesize = reader.getPageSizeWithRotation(i); 106 | x = (pagesize.getLeft() + pagesize.getRight()) / 2; 107 | y = (pagesize.getTop() + pagesize.getBottom()) / 2; 108 | over = stamper.getOverContent(i); 109 | over.saveState(); 110 | over.setGState(gs1); 111 | if (i % 2 == 1) 112 | ColumnText.showTextAligned(over, Element.ALIGN_CENTER, p, x, y, 0); 113 | else 114 | over.addImage(img, w, 0, 0, h, x - (w / 2), y - (h / 2)); 115 | over.restoreState(); 116 | } 117 | stamper.close(); 118 | reader.close(); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/samples/WatermarkPptTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.samples; 5 | 6 | import java.awt.geom.Rectangle2D; 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.FileOutputStream; 10 | import java.io.IOException; 11 | 12 | import org.apache.poi.sl.usermodel.PictureData.PictureType; 13 | import org.apache.poi.xslf.usermodel.SlideLayout; 14 | import org.apache.poi.xslf.usermodel.XMLSlideShow; 15 | import org.apache.poi.xslf.usermodel.XSLFAutoShape; 16 | import org.apache.poi.xslf.usermodel.XSLFPictureData; 17 | import org.apache.poi.xslf.usermodel.XSLFPictureShape; 18 | import org.apache.poi.xslf.usermodel.XSLFSlide; 19 | import org.apache.poi.xslf.usermodel.XSLFSlideLayout; 20 | import org.apache.poi.xslf.usermodel.XSLFSlideMaster; 21 | import org.junit.Test; 22 | 23 | /** 24 | * @author eko.zhan 25 | * @date 2018年9月3日 下午7:27:58 26 | * @version 1.0 27 | */ 28 | public class WatermarkPptTests { 29 | 30 | @Test 31 | public void test1() throws IOException { 32 | // create a ppt 33 | XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("E:\\ConvertTester\\ppt\\看看addThread方法的源码.pptx")); 34 | XSLFPictureData pd = ppt.addPicture(new File("E:\\ConvertTester\\images\\jshrss-logo.png"), PictureType.PNG); 35 | for (int i=0;ieko.zhan 30 | * @date 2018年8月31日 下午1:41:38 31 | * @version 1.0 32 | */ 33 | public class WatermarkWordTests extends BaseTests { 34 | 35 | /** 36 | * 给 docx 文件加水印 37 | * @author eko.zhan at 2018年8月31日 下午1:41:50 38 | * @throws IOException 39 | */ 40 | @Test 41 | public void testDocx() throws IOException { 42 | String filepath = "E:\\ConvertTester\\docx\\NVR5X-I人脸比对配置-ekozhan.docx"; 43 | 44 | WatermarkServiceImpl service = new WatermarkServiceImpl(); 45 | byte[] bytes = service.handle(new File(filepath), "中华民国100"); 46 | // FileOutputStream out = new FileOutputStream("E:\\1.docx"); 47 | // IOUtils.write(bytes, out); 48 | try (FileOutputStream out = new FileOutputStream("E:\\1.docx")){ 49 | IOUtils.write(bytes, out); 50 | } 51 | } 52 | 53 | @Test 54 | public void testDocx2() throws IOException { 55 | String filepath = "E:\\ConvertTester\\docx\\NVR5X-I人脸比对配置-ekozhan.docx"; 56 | XWPFDocument doc = new XWPFDocument(new FileInputStream(filepath)); 57 | XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(doc); 58 | 59 | policy.createWatermark("ekozhan123"); 60 | doc.write(new FileOutputStream("E:\\ConvertTester\\docx\\NVR5X-I人脸比对配置-ekozhan-11.docx")); 61 | doc.close(); 62 | } 63 | 64 | @Test 65 | public void testDoc() throws IOException { 66 | String filepath = "E:\\ConvertTester\\docx\\请稍候在注册表里注册.doc"; 67 | File originFile = new File(filepath); 68 | InputStream in = new FileInputStream(originFile); 69 | HWPFDocument doc = new HWPFDocument(in); 70 | 71 | if ( doc.getOfficeDrawingsHeaders() != null ) 72 | { 73 | System.out.println( "=== Document part: HEADER ===" ); 74 | for ( OfficeDrawing officeDrawing : doc 75 | .getOfficeDrawingsHeaders().getOfficeDrawings() ) 76 | { 77 | System.out.println( officeDrawing ); 78 | } 79 | } 80 | if ( doc.getOfficeDrawingsHeaders() != null ) 81 | { 82 | System.out.println( "=== Document part: MAIN ===" ); 83 | for ( OfficeDrawing officeDrawing : doc 84 | .getOfficeDrawingsMain().getOfficeDrawings() ) 85 | { 86 | System.out.println( officeDrawing ); 87 | } 88 | } 89 | 90 | if (true) return; 91 | OfficeDrawings officeDrawings = doc.getOfficeDrawingsHeaders(); 92 | OfficeDrawing officeDrawingAt = officeDrawings.getOfficeDrawingAt(0); 93 | Collection officeDrawings2 = officeDrawings.getOfficeDrawings(); 94 | OfficeDrawing drawing = doc.getOfficeDrawingsHeaders().getOfficeDrawings().iterator().next(); 95 | EscherContainerRecord escherContainerRecord = drawing.getOfficeArtSpContainer(); 96 | 97 | EscherOptRecord officeArtFOPT = escherContainerRecord.getChildById((short) 0xF00B); 98 | EscherComplexProperty gtextUNICODE = officeArtFOPT.lookup(0x00c0); 99 | String text = StringUtil.getFromUnicodeLE(gtextUNICODE.getComplexData()); 100 | System.out.println(text); 101 | doc.close(); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/util/BaseTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import java.io.File; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | import org.apache.commons.lang3.StringUtils; 11 | import org.artofsolving.jodconverter.OfficeDocumentConverter; 12 | import org.artofsolving.jodconverter.document.DefaultDocumentFormatRegistry; 13 | import org.artofsolving.jodconverter.document.DocumentFormatRegistry; 14 | import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration; 15 | import org.artofsolving.jodconverter.office.OfficeManager; 16 | 17 | import com.sun.star.document.UpdateDocMode; 18 | 19 | /** 20 | * @author eko.zhan 21 | * @date 2018年9月2日 下午1:23:34 22 | * @version 1.0 23 | */ 24 | public class BaseTests { 25 | 26 | 27 | private String libreOfficeDirPath = "D:/Programs/LibreOffice"; 28 | 29 | protected void convert(File inputFile, File outputFile){ 30 | DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); 31 | configuration.setPortNumber(8100); 32 | configuration.setOfficeHome(new File(libreOfficeDirPath)); 33 | // configuration.setOfficeHome(new File("D:/Program Files/OpenOffice")); 34 | 35 | OfficeManager officeManager = configuration.buildOfficeManager(); 36 | officeManager.start(); 37 | DocumentFormatRegistry formatRegistry = new DefaultDocumentFormatRegistry(); 38 | OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager, formatRegistry); 39 | 40 | try { 41 | converter.convert(inputFile, outputFile); 42 | } catch (Exception e){ 43 | e.printStackTrace(); 44 | } finally { 45 | officeManager.stop(); 46 | } 47 | } 48 | 49 | protected void convert(File inputFile, File outputFile, String password){ 50 | DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); 51 | configuration.setPortNumber(8100); 52 | configuration.setOfficeHome(new File(libreOfficeDirPath)); 53 | // configuration.setOfficeHome(new File("D:/Program Files/OpenOffice")); 54 | 55 | OfficeManager officeManager = configuration.buildOfficeManager(); 56 | officeManager.start(); 57 | DocumentFormatRegistry formatRegistry = new DefaultDocumentFormatRegistry(); 58 | OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager, formatRegistry); 59 | Map defaultLoadProperties = createDefaultLoadProperties(password); 60 | converter.setDefaultLoadProperties(defaultLoadProperties); 61 | try { 62 | converter.convert(inputFile, outputFile); 63 | } catch (Exception e){ 64 | e.printStackTrace(); 65 | } finally { 66 | officeManager.stop(); 67 | } 68 | } 69 | 70 | protected Map createDefaultLoadProperties(String password) { 71 | Map loadProperties = new HashMap(); 72 | loadProperties.put("Hidden", true); 73 | loadProperties.put("ReadOnly", true); 74 | loadProperties.put("UpdateDocMode", UpdateDocMode.QUIET_UPDATE); 75 | if (StringUtils.isNotBlank(password)){ 76 | loadProperties.put("Password", password); 77 | } 78 | return loadProperties; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/util/ConvertTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | import java.io.IOException; 9 | import java.util.Calendar; 10 | import java.util.Map; 11 | 12 | import org.artofsolving.jodconverter.OfficeDocumentConverter; 13 | import org.artofsolving.jodconverter.document.DefaultDocumentFormatRegistry; 14 | import org.artofsolving.jodconverter.document.DocumentFamily; 15 | import org.artofsolving.jodconverter.document.DocumentFormat; 16 | import org.artofsolving.jodconverter.document.DocumentFormatRegistry; 17 | import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration; 18 | import org.artofsolving.jodconverter.office.OfficeManager; 19 | import org.junit.Test; 20 | 21 | /** 22 | * @author eko.zhan 23 | * @date 2017年12月6日 下午7:55:08 24 | * @version 1.0 25 | */ 26 | public class ConvertTests extends BaseTests { 27 | 28 | @Test 29 | public void testDocToXml(){ 30 | File inputFile = new File("E:/converter-html/local/4.25-1.doc"); 31 | File outputFile = new File("E:/converter-html/local/4.25-1.doc.xml"); 32 | //IOUtils.copy(new FileInputStream(inputFile), new FileOutputStream(outputFile)); 33 | convert(inputFile, outputFile); 34 | } 35 | 36 | 37 | @Test 38 | public void testEncrypt(){ 39 | File inputFile = new File("E:/ConvertTester/encrypt/I_am_encrypt.docx"); 40 | File outputFile = new File("E:/ConvertTester/encrypt/I_am_encrypt.html"); 41 | convert(inputFile, outputFile, "xiaoi"); 42 | } 43 | 44 | @Test 45 | public void testVisioAsPdf(){ 46 | File inputFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx.vsdx"); 47 | File outputFile = new File("E:/ConvertTester/TestFiles/I_am_a_vsdx_libreoffice.pdf"); 48 | convert(inputFile, outputFile); 49 | } 50 | 51 | @Test 52 | public void testDocToDocx() throws FileNotFoundException, IOException{ 53 | 54 | File inputFile = new File("E:/ConvertTester/CeairFile/2015120209414170.doc"); 55 | File outputFile = new File("E:/ConvertTester/CeairFile/2015120209414170.docx"); 56 | //IOUtils.copy(new FileInputStream(inputFile), new FileOutputStream(outputFile)); 57 | convert(inputFile, outputFile); 58 | } 59 | 60 | @Test 61 | public void testPptToPdf() throws FileNotFoundException, IOException{ 62 | 63 | File inputFile = new File("E:/ConvertTester/ppt/1527243826237.ppt"); 64 | File outputFile = new File("E:/ConvertTester/ppt/1527243826237.pdf"); 65 | convert(inputFile, outputFile); 66 | } 67 | 68 | @Test 69 | public void testConvert() throws IOException { 70 | // File inputFile = new File("D:/Workspace/kbase-doc/target/classes/static/DATAS/1512561737109/1.doc"); 71 | File inputFile = new File("D:/Workspace/kbase-doc/target/classes/static/DATAS/1512561737109/1512561737109.html"); 72 | File outputFile = new File("D:/Workspace/kbase-doc/target/classes/static/DATAS/1512561737109/" + Calendar.getInstance().getTimeInMillis() + ".docx"); 73 | // if (!outputFile.exists()){ 74 | // outputFile.createNewFile(); 75 | // } 76 | DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); 77 | configuration.setPortNumber(8100); 78 | configuration.setOfficeHome(new File("D:/Program Files/LibreOffice")); 79 | 80 | OfficeManager officeManager = configuration.buildOfficeManager(); 81 | officeManager.start(); 82 | DocumentFormatRegistry formatRegistry = new DefaultDocumentFormatRegistry(); 83 | OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager, formatRegistry); 84 | 85 | try { 86 | converter.convert(inputFile, outputFile); 87 | } catch (Exception e){ 88 | e.printStackTrace(); 89 | } finally { 90 | officeManager.stop(); 91 | } 92 | } 93 | 94 | @Test 95 | public void testGetFormatByExtension(){ 96 | DocumentFormatRegistry formatRegistry = new DefaultDocumentFormatRegistry(); 97 | DocumentFormat formatByExtension = formatRegistry.getFormatByExtension("docx"); 98 | System.out.println(formatByExtension.getName()); 99 | Map> storePropertiesByFamily = formatByExtension.getStorePropertiesByFamily(); 100 | System.out.println(storePropertiesByFamily.size()); 101 | 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/util/FormFieldTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Powered by http://www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import org.apache.poi.hwpf.HWPFDocument; 7 | import org.apache.poi.hwpf.model.FieldsDocumentPart; 8 | import org.apache.poi.hwpf.usermodel.Field; 9 | import org.apache.poi.hwpf.usermodel.Paragraph; 10 | import org.apache.poi.xwpf.usermodel.XWPFDocument; 11 | import org.apache.poi.xwpf.usermodel.XWPFParagraph; 12 | import org.apache.poi.xwpf.usermodel.XWPFTable; 13 | import org.apache.xmlbeans.XmlCursor; 14 | import org.apache.xmlbeans.XmlException; 15 | import org.apache.xmlbeans.XmlObject; 16 | import org.junit.Test; 17 | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTP; 18 | 19 | import javax.xml.namespace.QName; 20 | import java.io.FileInputStream; 21 | import java.io.IOException; 22 | import java.util.List; 23 | 24 | /** 25 | * poi 操作 word form field 26 | * @author eko.zhan 27 | * @version v1.0 28 | * @date 2019/8/19 18:23 29 | */ 30 | public class FormFieldTests { 31 | 32 | @Test 33 | public void testTextBox() { 34 | 35 | } 36 | 37 | 38 | @Test 39 | public void testDocx() throws IOException { 40 | XWPFDocument document = new XWPFDocument(new FileInputStream("D:\\Xiaoi\\Items\\2019-07-02 合同智能分析工具\\04_现场数据\\4.25国网北京信通公司110kV半壁店站等63个站点通信蓄电池改造勘察设计合同.docx")); 41 | 42 | List paragraphs = document.getParagraphs(); 43 | List tables = document.getTables(); 44 | for (XWPFTable table : tables){ 45 | } 46 | for (XWPFParagraph paragraph : paragraphs){ 47 | // System.out.println(paragraph.getCTP().xmlText()); 48 | printContentsOfTextBox(paragraph); 49 | } 50 | } 51 | 52 | private void printContentsOfTextBox(XWPFParagraph paragraph) { 53 | //declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' 54 | // declare namespace wps='http://schemas.microsoft.com/office/word/2010/wordprocessingShape' .//*/wps:txbx/w:txbxContent 55 | String NS_W = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"; 56 | String queryExpression = 57 | "declare namespace w='" + NS_W + "';" + 58 | "$this/w:permStart"; 59 | XmlObject[] textBoxObjects = paragraph.getCTP().selectPath(queryExpression); 60 | 61 | if (textBoxObjects.length>0){ 62 | for (XmlObject xmlObject : textBoxObjects){ 63 | XmlCursor xmlCursor = xmlObject.newCursor(); 64 | 65 | // permStart 前面的 r 是主要内容 66 | 67 | String tmp = ""; 68 | while (xmlCursor.toNextSibling()){ 69 | tmp += xmlCursor.getTextValue().trim(); 70 | // r / permStart 71 | if (("permEnd").equals(xmlCursor.getName().getLocalPart())){ 72 | break; 73 | } 74 | } 75 | System.out.println(tmp); 76 | } 77 | } 78 | 79 | // for (int i =0; i < textBoxObjects.length; i++) { 80 | // XWPFParagraph embeddedPara = null; 81 | // try { 82 | // XmlObject[] paraObjects = textBoxObjects[i]. 83 | // selectChildren( 84 | // new QName("http://schemas.openxmlformats.org/wordprocessingml/2006/main", "p")); 85 | // 86 | // for (int j=0; jeko.zhan 10 | * @date 2017年8月11日 上午10:04:33 11 | * @version 1.0 12 | */ 13 | public class HtmlUtilsTests { 14 | 15 | @Test 16 | public void replaceCharset(){ 17 | String data = "CONTENT=\"text/html; charset=gb2312\""; 18 | String s = HtmlUtils.replaceCharset(data); 19 | System.out.println(s); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/util/PdfToHtmlTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.util; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.io.IOException; 9 | import java.io.OutputStreamWriter; 10 | 11 | import javax.xml.parsers.ParserConfigurationException; 12 | 13 | import org.apache.pdfbox.pdmodel.PDDocument; 14 | import org.apache.pdfbox.pdmodel.encryption.InvalidPasswordException; 15 | import org.fit.pdfdom.PDFDomTree; 16 | import org.junit.Test; 17 | import org.w3c.dom.Document; 18 | 19 | /** 20 | * @author eko.zhan 21 | * @date 2018年7月10日 下午5:00:24 22 | * @version 1.0 23 | */ 24 | public class PdfToHtmlTests { 25 | 26 | @Test 27 | public void pdf2html() throws InvalidPasswordException, IOException, ParserConfigurationException{ 28 | String srcFilePath = "E:\\converter-html\\sgcc\\京电发展〔2019〕82号(盖章).ceb"; 29 | String destFilePath = srcFilePath + ".html"; 30 | PDDocument pdf = PDDocument.load(new File(srcFilePath)); 31 | PDFDomTree parser = new PDFDomTree(); 32 | // Document dom = parser.createDOM(pdf); 33 | File htmlFile = new File(destFilePath); 34 | parser.writeText(pdf, new OutputStreamWriter(new FileOutputStream(htmlFile))); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/ExcelProcessorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | /** 6 | * @author eko.zhan 7 | * @date 2018年9月17日 下午2:11:36 8 | * @version 1.0 9 | */ 10 | 11 | import java.io.File; 12 | 13 | import org.junit.Test; 14 | 15 | public class ExcelProcessorTests { 16 | 17 | @Test 18 | public void testProcess() throws WatermarkException { 19 | File file = new File("E:\\ConvertTester\\excel\\什么是中央处理器.xlsx"); 20 | File imgFile = new File("E:\\ConvertTester\\images\\jshrss-logo.png"); 21 | 22 | ExcelProcessor excelProcessor = new ExcelProcessor(file, imgFile); 23 | excelProcessor.process(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/FontImageTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | /** 6 | * @author eko.zhan 7 | * @date 2018年9月18日 上午10:20:55 8 | * @version 1.0 9 | */ 10 | 11 | import org.junit.Test; 12 | 13 | public class FontImageTests { 14 | 15 | @Test 16 | public void testCreateImage() throws WatermarkException { 17 | FontImage.createImage("江苏人社-jshrss"); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/ImageProcessorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | 8 | import org.junit.Test; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @date 2018年9月17日 下午5:03:51 13 | * @version 1.0 14 | */ 15 | public class ImageProcessorTests { 16 | 17 | @Test 18 | public void testProcess() { 19 | File file = new File("E:\\ConvertTester\\images\\2.png"); 20 | File imgFile = new File("E:\\ConvertTester\\images\\jshrss-logo-s.png"); 21 | 22 | ImageProcessor processor = new ImageProcessor(file, imgFile); 23 | try { 24 | processor.process(); 25 | } catch (WatermarkException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/PdfProcessorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | 8 | import org.junit.Test; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @date 2018年9月17日 下午5:03:51 13 | * @version 1.0 14 | */ 15 | public class PdfProcessorTests { 16 | 17 | @Test 18 | public void testProcess() { 19 | File file = new File("E:\\ConvertTester\\pdf\\增值税开票_ekozhan.pdf"); 20 | File imgFile = new File("E:\\ConvertTester\\images\\jshrss-logo-s.png"); 21 | 22 | PdfProcessor processor = new PdfProcessor(file, imgFile); 23 | try { 24 | processor.process(); 25 | } catch (WatermarkException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/PowerPointProcessorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | /** 6 | * @author eko.zhan 7 | * @date 2018年9月17日 下午4:33:28 8 | * @version 1.0 9 | */ 10 | 11 | import java.io.File; 12 | 13 | import org.junit.Test; 14 | 15 | public class PowerPointProcessorTests { 16 | 17 | @Test 18 | public void testProcess() { 19 | File file = new File("E:\\ConvertTester\\ppt\\看看addThread方法的源码1.pptx"); 20 | File imgFile = new File("E:\\ConvertTester\\images\\jshrss-logo.png"); 21 | 22 | PowerPointProcessor processor = new PowerPointProcessor(file, imgFile); 23 | try { 24 | processor.process(); 25 | } catch (WatermarkException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/WatermarkProcessorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | 6 | import java.io.File; 7 | 8 | import org.junit.Test; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @date 2018年9月18日 上午9:49:25 13 | * @version 1.0 14 | */ 15 | public class WatermarkProcessorTests { 16 | 17 | @Test 18 | public void testProcessor() throws WatermarkException { 19 | File file = new File("E:\\ConvertTester\\excel\\什么是中央处理器.xlsx"); 20 | File imgFile = new File("E:\\ConvertTester\\images\\jshrss-logo.png"); 21 | 22 | WatermarkProcessor.process(file, imgFile); 23 | } 24 | 25 | @Test 26 | public void testProcessorText() throws WatermarkException { 27 | File file = new File("E:\\ConvertTester\\excel\\什么是中央处理器.xlsx"); 28 | WatermarkProcessor.process(file, "小i机器人"); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/watermark/WordProcessorTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.watermark; 5 | /** 6 | * @author eko.zhan 7 | * @date 2018年9月17日 上午11:22:38 8 | * @version 1.0 9 | */ 10 | 11 | import java.io.File; 12 | 13 | import org.junit.Test; 14 | 15 | public class WordProcessorTests { 16 | 17 | @Test 18 | public void testProcess() { 19 | File file = new File("E:\\ConvertTester\\docx\\NVR5X-I人脸比对配置-ekozhan1.docx"); 20 | File imgFile = new File("E:\\ConvertTester\\images\\jshrss-logo.png"); 21 | 22 | WordProcessor wordProcesser = new WordProcessor(file, imgFile); 23 | try { 24 | wordProcesser.process(); 25 | } catch (WatermarkException e) { 26 | e.printStackTrace(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /kbase-doc-alpha/src/test/java/com/eastrobot/doc/web/controller/IndexControllerTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.eastrobot.doc.web.controller; 5 | 6 | import java.io.File; 7 | import java.io.IOException; 8 | 9 | import org.apache.http.HttpEntity; 10 | import org.apache.http.client.ClientProtocolException; 11 | import org.apache.http.client.methods.CloseableHttpResponse; 12 | import org.apache.http.client.methods.HttpPost; 13 | import org.apache.http.entity.ContentType; 14 | import org.apache.http.entity.mime.MultipartEntityBuilder; 15 | import org.apache.http.entity.mime.content.FileBody; 16 | import org.apache.http.entity.mime.content.StringBody; 17 | import org.apache.http.impl.client.CloseableHttpClient; 18 | import org.apache.http.impl.client.HttpClients; 19 | import org.apache.http.util.EntityUtils; 20 | 21 | /** 22 | * @author eko.zhan 23 | * @date 2017年8月19日 下午8:47:29 24 | * @version 1.0 25 | */ 26 | public class IndexControllerTests implements Runnable{ 27 | 28 | public static void main(String[] args) throws InterruptedException { 29 | int interval = 1; 30 | IndexControllerTests indexControllerTests = new IndexControllerTests(); 31 | for (int i=0; i<20; i++){ 32 | indexControllerTests.run(); 33 | System.out.println("当前线程[" + Thread.currentThread().getName() + "]停顿" + interval + "秒"); 34 | Thread.currentThread().sleep(1000*interval); 35 | } 36 | } 37 | 38 | public void run() { 39 | CloseableHttpClient httpclient = HttpClients.createDefault(); 40 | try { 41 | HttpPost httppost = new HttpPost("http://localhost:8080" + 42 | "/kbase-doc/index/uploadData"); 43 | 44 | FileBody bin = new FileBody(new File("E:\\ConvertTester\\myhot\\en-acc.doc")); 45 | StringBody comment = new StringBody("A binary file of some kind", ContentType.TEXT_PLAIN); 46 | 47 | HttpEntity reqEntity = MultipartEntityBuilder.create() 48 | .addPart("uploadFile", bin) 49 | .addPart("comment", comment) 50 | .build(); 51 | 52 | httppost.setEntity(reqEntity); 53 | 54 | System.out.println("executing request " + httppost.getRequestLine()); 55 | CloseableHttpResponse response = httpclient.execute(httppost); 56 | try { 57 | System.out.println("----------------------------------------"); 58 | System.out.println(response.getStatusLine()); 59 | HttpEntity resEntity = response.getEntity(); 60 | if (resEntity != null) { 61 | System.out.println("Response content length: " + resEntity.getContentLength()); 62 | } 63 | EntityUtils.consume(resEntity); 64 | } finally { 65 | response.close(); 66 | } 67 | } catch (ClientProtocolException e) { 68 | // TODO Auto-generated catch block 69 | e.printStackTrace(); 70 | } catch (IOException e) { 71 | // TODO Auto-generated catch block 72 | e.printStackTrace(); 73 | } finally { 74 | try { 75 | httpclient.close(); 76 | } catch (IOException e) { 77 | e.printStackTrace(); 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /kbase-doc-beta/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | kbase-doc 7 | com.eastrobot 8 | 0.0.1-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | kbase-doc-beta 13 | 14 | 15 | 4.4.4 16 | 7.4.1 17 | 18 | 19 | 20 | 21 | 22 | 28 | 29 | org.jodconverter 30 | jodconverter-local 31 | ${jodconverter.version} 32 | 33 | 34 | 35 | org.jodconverter 36 | jodconverter-spring-boot-starter 37 | ${jodconverter.version} 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | io.springfox 70 | springfox-boot-starter 71 | 3.0.0 72 | 73 | 74 | 75 | 76 | org.springframework.boot 77 | spring-boot-devtools 78 | runtime 79 | 80 | 81 | org.projectlombok 82 | lombok 83 | true 84 | 85 | 86 | org.springframework.boot 87 | spring-boot-starter-test 88 | test 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/KbaseDocBetaApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc; 5 | 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.scheduling.annotation.EnableAsync; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @version v1.0 13 | * @date 2022/10/21 20:04 14 | */ 15 | @SpringBootApplication 16 | @EnableAsync 17 | public class KbaseDocBetaApplication { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(KbaseDocBetaApplication.class, args); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/config/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc.config; 5 | 6 | import org.springframework.context.annotation.Configuration; 7 | import springfox.documentation.oas.annotations.EnableOpenApi; 8 | 9 | /** 10 | * swagger3 11 | * @author eko.zhan 12 | * @version v1.0 13 | * @date 2022/10/22 13:07 14 | */ 15 | @Configuration 16 | @EnableOpenApi 17 | public class SwaggerConfig { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/config/SystemConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc.config; 5 | 6 | /** 7 | * @author eko.zhan 8 | * @version v1.0 9 | * @date 2022/10/22 12:49 10 | */ 11 | public class SystemConstants { 12 | 13 | /** 14 | * 目标文件后缀 15 | */ 16 | public final static String OUTPUT_EXTENSION = "html"; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/dao/AttachmentRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc.dao; 5 | 6 | import com.ibothub.doc.entity.Attachment; 7 | import org.springframework.data.repository.CrudRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @version v1.0 13 | * @date 2022/10/18 21:00 14 | */ 15 | @Repository 16 | public interface AttachmentRepository extends CrudRepository { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/entity/Attachment.java: -------------------------------------------------------------------------------- 1 | package com.ibothub.doc.entity; 2 | 3 | import java.io.Serializable; 4 | import java.time.LocalDateTime; 5 | import javax.persistence.Entity; 6 | import javax.persistence.GeneratedValue; 7 | import javax.persistence.GenerationType; 8 | import javax.persistence.Id; 9 | import javax.persistence.Table; 10 | import javax.persistence.Transient; 11 | import lombok.AllArgsConstructor; 12 | import lombok.Builder; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | /** 17 | * @author eko.zhan 18 | * @version 1.0 19 | * @date 2021/6/29 20:09 20 | */ 21 | @Data 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | @Builder 25 | @Entity 26 | @Table(name = "attachment") 27 | public class Attachment implements Serializable { 28 | 29 | @Id 30 | @GeneratedValue(strategy = GenerationType.IDENTITY) 31 | private Long id; 32 | 33 | /** 34 | * 源文件路径 35 | */ 36 | private String path; 37 | 38 | /** 39 | * 目标文件路径 40 | */ 41 | private String targetPath; 42 | 43 | /** 44 | * 文件显示名称 45 | */ 46 | private String name; 47 | 48 | private Long size; 49 | 50 | /** 51 | * 文档大小,用于显示 52 | */ 53 | @Transient 54 | private String sizeAlias; 55 | 56 | /** 57 | * 0-待转换;1-已转换;-1-转换失败 58 | */ 59 | private Integer status; 60 | 61 | private LocalDateTime createTime; 62 | 63 | } 64 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/service/AttachmentService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc.service; 5 | 6 | import com.ibothub.doc.entity.Attachment; 7 | import java.io.IOException; 8 | import org.springframework.web.multipart.MultipartFile; 9 | 10 | /** 11 | * @author eko.zhan 12 | * @version v1.0 13 | * @date 2022/10/22 12:44 14 | */ 15 | public interface AttachmentService { 16 | 17 | void upload(MultipartFile uploadFile) throws IOException; 18 | 19 | Iterable list(); 20 | } 21 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/service/impl/AttachmentServiceImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc.service.impl; 5 | 6 | import com.google.common.collect.Streams; 7 | import com.ibothub.doc.config.SystemConstants; 8 | import com.ibothub.doc.dao.AttachmentRepository; 9 | import com.ibothub.doc.entity.Attachment; 10 | import com.ibothub.doc.service.AttachmentService; 11 | import com.ibothub.doc.util.FileExtensionUtils; 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.time.LocalDateTime; 15 | import java.util.concurrent.CompletableFuture; 16 | import java.util.stream.Collectors; 17 | import javax.annotation.Resource; 18 | import org.apache.commons.io.FilenameUtils; 19 | import org.jodconverter.core.DocumentConverter; 20 | import org.jodconverter.core.office.OfficeException; 21 | import org.springframework.stereotype.Service; 22 | import org.springframework.util.FileCopyUtils; 23 | import org.springframework.util.ResourceUtils; 24 | import org.springframework.web.multipart.MultipartFile; 25 | 26 | /** 27 | * @author eko.zhan 28 | * @version v1.0 29 | * @date 2022/10/22 12:44 30 | */ 31 | @Service 32 | public class AttachmentServiceImpl implements AttachmentService { 33 | 34 | 35 | @Resource 36 | AttachmentRepository attachmentRepository; 37 | 38 | @Resource 39 | DocumentConverter documentConverter; 40 | 41 | 42 | @Override 43 | public void upload(MultipartFile multipartFile) throws IOException { 44 | File targetDir = ResourceUtils.getFile("classpath:static/DATAS/"); 45 | String inputExtension = FilenameUtils.getExtension(multipartFile.getOriginalFilename()); 46 | 47 | Attachment attachment = Attachment.builder() 48 | .name(multipartFile.getOriginalFilename()) 49 | .size(multipartFile.getSize()) 50 | // 待转换 51 | .status(0) 52 | .createTime(LocalDateTime.now()) 53 | .build(); 54 | attachmentRepository.save(attachment); 55 | String inputFilename = attachment.getId() + ""; 56 | 57 | File file = new File(targetDir.getAbsolutePath() + "/" + inputFilename + "." + inputExtension); 58 | FileCopyUtils.copy(multipartFile.getBytes(), file); 59 | 60 | File outputFile = new File(targetDir.getAbsolutePath() + "/" + inputFilename + 61 | "/" + inputFilename + "." + SystemConstants.OUTPUT_EXTENSION); 62 | 63 | // 保存源文件和目标文件的路径 64 | attachment.setPath(file.getPath()); 65 | attachment.setTargetPath(outputFile.getPath()); 66 | attachmentRepository.save(attachment); 67 | 68 | CompletableFuture.runAsync(()->{ 69 | try { 70 | documentConverter 71 | .convert(file) 72 | .to(outputFile) 73 | .execute(); 74 | } catch (OfficeException e) { 75 | // 转换失败 76 | attachment.setStatus(-1); 77 | attachmentRepository.save(attachment); 78 | } 79 | }/*, threadPoolExecutor*/).whenComplete((result, e) -> { 80 | // 转换成功 81 | attachment.setStatus(1); 82 | attachmentRepository.save(attachment); 83 | }); 84 | } 85 | 86 | @Override 87 | public Iterable list() { 88 | return Streams.stream(attachmentRepository.findAll()) 89 | .peek(attachment -> { 90 | attachment.setSizeAlias(FileExtensionUtils.readFilesize(attachment.getSize())); 91 | }) 92 | .collect(Collectors.toList()); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/util/FileExtensionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Power by www.xiaoi.com 3 | */ 4 | package com.ibothub.doc.util; 5 | 6 | import java.text.DecimalFormat; 7 | import org.apache.commons.io.FilenameUtils; 8 | import org.apache.commons.lang3.ArrayUtils; 9 | 10 | /** 11 | * 12 | * @author eko.zhan 13 | * @date 2017年12月21日 下午3:10:34 14 | * @version 1.0 15 | */ 16 | public class FileExtensionUtils { 17 | 18 | private static String[] videoArray = new String[]{"mp4", "avi", "wma", "rmvb", "rm", "flash", "mid", "3gp"}; 19 | private static String[] imageArray = new String[]{"jpg", "jpeg", "png", "gif", "ico", "bmp"}; 20 | private static String[] audioArray = new String[]{"mp3", "wav", "ogg"}; 21 | private static String[] officeArray = new String[]{"doc", "docx", "xls", "xlsx", "ppt", "pptx"}; 22 | 23 | /** 24 | * 是否是视频文件 25 | * @author eko.zhan at 2017年12月21日 下午3:38:28 26 | * @return 27 | */ 28 | public static Boolean isVideo(String filename){ 29 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 30 | if (ArrayUtils.contains(videoArray, extension)){ 31 | return true; 32 | } 33 | return false; 34 | } 35 | /** 36 | * 是否是图片 37 | * @author eko.zhan at 2017年12月21日 下午3:47:18 38 | * @param filename 39 | * @return 40 | */ 41 | public static Boolean isImage(String filename){ 42 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 43 | if (ArrayUtils.contains(imageArray, extension)){ 44 | return true; 45 | } 46 | return false; 47 | } 48 | /** 49 | * 是否是Office文件 50 | * @author eko.zhan at Jan 3, 2018 5:30:52 PM 51 | * @param filename 52 | * @return 53 | */ 54 | public static Boolean isOffice(String filename){ 55 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 56 | if (ArrayUtils.contains(officeArray, extension)){ 57 | return true; 58 | } 59 | return false; 60 | } 61 | /** 62 | * 是否是音频文件 63 | * @author eko.zhan at Jan 5, 2018 3:41:36 PM 64 | * @param filename 65 | * @return 66 | */ 67 | public static Boolean isAudio(String filename) { 68 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 69 | if (ArrayUtils.contains(audioArray, extension)){ 70 | return true; 71 | } 72 | return false; 73 | } 74 | /** 75 | * 是否是Excel文件 76 | * @author eko.zhan at Aug 7, 2018 11:33:06 AM 77 | * @param filename 78 | * @return 79 | */ 80 | public static Boolean isExcel(String filename){ 81 | String[] arr = new String[]{"xls", "xlsx"}; 82 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 83 | if (ArrayUtils.contains(arr, extension)){ 84 | return true; 85 | } 86 | return false; 87 | } 88 | /** 89 | * 是否是Word文件 90 | * @author eko.zhan at Aug 7, 2018 11:33:06 AM 91 | * @param filename 92 | * @return 93 | */ 94 | public static Boolean isWord(String filename){ 95 | String[] arr = new String[]{"doc", "docx"}; 96 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 97 | if (ArrayUtils.contains(arr, extension)){ 98 | return true; 99 | } 100 | return false; 101 | } 102 | /** 103 | * 是否是 ppt 文件 104 | * @author eko.zhan at 2018年9月1日 上午10:16:11 105 | * @param filename 106 | * @return 107 | */ 108 | public static Boolean isPpt(String filename) { 109 | String[] arr = new String[]{"ppt", "pptx"}; 110 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 111 | if (ArrayUtils.contains(arr, extension)){ 112 | return true; 113 | } 114 | return false; 115 | } 116 | /** 117 | * 是否是 Word 或 Excel 文件 118 | * @author eko.zhan at Aug 7, 2018 11:37:50 AM 119 | * @param filename 120 | * @return 121 | */ 122 | public static Boolean isWordOrExcel(String filename){ 123 | return isWord(filename) || isExcel(filename); 124 | } 125 | /** 126 | * 是否是 office 或 pdf 文件 127 | * @author eko.zhan at Aug 7, 2018 11:45:10 AM 128 | * @param filename 129 | * @return 130 | */ 131 | public static Boolean isOfficeOrPdf(String filename){ 132 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 133 | if (isOffice(filename) || "pdf".equals(extension)){ 134 | return Boolean.TRUE; 135 | }else{ 136 | return Boolean.FALSE; 137 | } 138 | } 139 | 140 | /** 141 | * 是否是 html 文件 142 | */ 143 | public static Boolean isHtml(String filename) { 144 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 145 | if ("html".equals(extension) || "htm".equals(extension)) { 146 | return Boolean.TRUE; 147 | } else { 148 | return Boolean.FALSE; 149 | } 150 | } 151 | 152 | /** 153 | * 是否是 pdf 文件 154 | */ 155 | public static Boolean isPdf(String filename) { 156 | String extension = FilenameUtils.getExtension(filename).toLowerCase(); 157 | if ("pdf".equals(extension)) { 158 | return Boolean.TRUE; 159 | } else { 160 | return Boolean.FALSE; 161 | } 162 | } 163 | 164 | public static String readFilesize(Long size) { 165 | final String[] units = new String[] {"B", "KB", "MB", "GB", "TB"}; 166 | int digitGroups = (int)(Math.log10(size) / Math.log10(1024)); 167 | return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) 168 | + " " + units[digitGroups]; 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/java/com/ibothub/doc/web/controller/IndexController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc.web.controller; 5 | 6 | import com.ibothub.doc.entity.Attachment; 7 | import com.ibothub.doc.service.AttachmentService; 8 | import java.io.IOException; 9 | import javax.annotation.Resource; 10 | import org.springframework.http.MediaType; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.web.bind.annotation.GetMapping; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | import org.springframework.web.bind.annotation.RequestParam; 16 | import org.springframework.web.bind.annotation.RequestPart; 17 | import org.springframework.web.bind.annotation.RestController; 18 | import org.springframework.web.multipart.MultipartFile; 19 | 20 | /** 21 | * @author eko.zhan 22 | * @version v1.0 23 | * @date 2022/10/22 12:41 24 | */ 25 | @RestController 26 | @RequestMapping("") 27 | public class IndexController { 28 | 29 | @Resource 30 | AttachmentService attachmentService; 31 | 32 | @RequestMapping(value = "/upload", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }, method = RequestMethod.POST) 33 | public ResponseEntity upload(@RequestPart @RequestParam("uploadFile") MultipartFile uploadFile){ 34 | try { 35 | attachmentService.upload(uploadFile); 36 | } catch (IOException e) { 37 | return ResponseEntity.ok(e.getMessage()); 38 | } 39 | return ResponseEntity.ok(""); 40 | } 41 | 42 | @GetMapping("/list") 43 | public ResponseEntity> list(){ 44 | return ResponseEntity.ok(attachmentService.list()); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | server.servlet.context-path=/ 3 | 4 | spring.servlet.multipart.max-file-size=50MB 5 | spring.servlet.multipart.max-request-size=50MB 6 | 7 | spring.devtools.restart.additional-exclude=application.properties 8 | 9 | # \u9A71\u52A8\u540D\u79F0 10 | spring.datasource.driver-class-name=org.sqlite.JDBC 11 | # \u6570\u636E\u5E93\u5730\u5740 12 | spring.datasource.url=jdbc:sqlite:ibothub.db 13 | # \u663E\u793A\u6570\u636E\u5E93\u64CD\u4F5C\u8BB0\u5F55 14 | spring.jpa.show-sql=true 15 | # \u6BCF\u6B21\u542F\u52A8\u66F4\u6539\u6570\u636E\u8868\u7ED3\u6784 16 | spring.jpa.hibernate.ddl-auto=update 17 | 18 | jodconverter.local.enabled=true 19 | jodconverter.local.office-home=D:/Programs/LibreOffice 20 | jodconverter.local.port-numbers[0]=8100 21 | jodconverter.local.port-numbers[1]=8101 22 | jodconverter.local.port-numbers[2]=8102 23 | -------------------------------------------------------------------------------- /kbase-doc-beta/src/main/resources/static/DATAS/README.txt: -------------------------------------------------------------------------------- 1 | default catalog for attachment uploaded. -------------------------------------------------------------------------------- /kbase-doc-beta/src/test/java/com/ibothub/doc/service/ConverterTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * powered by http://ibothub.com 3 | */ 4 | package com.ibothub.doc.service; 5 | 6 | import java.io.File; 7 | import javax.annotation.Resource; 8 | import org.jodconverter.core.DocumentConverter; 9 | import org.jodconverter.core.document.DefaultDocumentFormatRegistry; 10 | import org.jodconverter.core.document.DocumentFormat; 11 | import org.jodconverter.core.office.OfficeException; 12 | import org.junit.Test; 13 | import org.junit.runner.RunWith; 14 | import org.springframework.boot.test.context.SpringBootTest; 15 | import org.springframework.test.context.junit4.SpringRunner; 16 | import org.springframework.util.Assert; 17 | 18 | /** 19 | * @author eko.zhan 20 | * @version v1.0 21 | * @date 2022/10/21 20:15 22 | */ 23 | @RunWith(SpringRunner.class) 24 | @SpringBootTest 25 | public class ConverterTests { 26 | 27 | @Resource 28 | DocumentConverter documentConverter; 29 | 30 | @Test 31 | public void testConvert() throws OfficeException { 32 | 33 | File inputFile = new File("D:\\Documents\\tmp\\1.docx"); 34 | File outputFile = new File("D:\\Documents\\tmp\\1\\1.html"); 35 | 36 | final DocumentFormat targetFormat = 37 | DefaultDocumentFormatRegistry.getFormatByExtension("html"); 38 | Assert.notNull(targetFormat, "targetFormat must not be null"); 39 | documentConverter 40 | .convert(inputFile) 41 | .as(targetFormat) 42 | .to(outputFile) 43 | .execute(); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-parent 10 | 2.3.12.RELEASE 11 | 12 | 13 | 14 | com.eastrobot 15 | kbase-doc 16 | 0.0.1-SNAPSHOT 17 | kbase-doc 18 | Converter office files to html 19 | 20 | pom 21 | 22 | 23 | kbase-doc-alpha 24 | kbase-doc-beta 25 | 26 | 27 | 28 | UTF-8 29 | UTF-8 30 | 1.8 31 | 1.2.83 32 | 5.2.3 33 | 3.6 34 | 2.7 35 | 2.9.2 36 | 3.41.2.2 37 | 0.1.2 38 | 32.0.0-jre 39 | 40 | 41 | 42 | 43 | org.springframework.boot 44 | spring-boot-starter-thymeleaf 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-web 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-data-jpa 53 | 54 | 55 | org.xerial 56 | sqlite-jdbc 57 | ${sqlite-jdbc.version} 58 | 59 | 60 | com.github.gwenn 61 | sqlite-dialect 62 | ${sqlite-dialect.version} 63 | 64 | 65 | com.alibaba 66 | fastjson 67 | ${fastjson.version} 68 | 69 | 70 | 71 | org.apache.commons 72 | commons-lang3 73 | ${commons.lang3.version} 74 | 75 | 76 | commons-io 77 | commons-io 78 | ${commons.io.version} 79 | 80 | 81 | 82 | com.google.guava 83 | guava 84 | ${guava.version} 85 | 86 | 87 | 88 | 89 | 90 | 91 | --------------------------------------------------------------------------------