Background
Recently, a company project to achieve a file upload and multi-document online preview function, has been doing wireless tool development, did not involve these things. In addition, the project team is short of java developers, and they are only a half-hanging front-end and a half-hanging java developers, so let me get a Demo first. I have searched a lot of information on the internet. Here I just sort it out for later reference.
Plug-ins and Toolkits
1. Display component of pdfjs-v1.7.225 front-end pdf format file
2.webuploader-0.1.5 Baidu File Upload Component
3.video-js-6.2.5 HTML 5 Video Player Component
4.openoffice-4.1.3 Locally installed, mainly for document to pdf program
5.jodconverter-core 3.0-beta-4 java calls the package of openoffice
Among them, pdfjs can be replaced by Viewer JS, which is relative to the encapsulation of the former. In addition, the java package jodconverter can also be replaced by com. artofsolution. jodconverter.2.2.1. According to what others said on the Internet and their own small test jodconverter.2.2.1 also converts pdf a little faster, but does not support the docx/xlsx/pptx file types after office 2003, that is to say, to customize java code can also achieve support, which is lazy to abandon. Yes.
Three, code
Bullshit talks about a lot of front-end code first, because it's Demo, the code is written very rough;
1. Main page index.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 7 <title>File Preview Demo</title> 8 <!-- jquery --> 9 <script src="./plugIns/jquery-3.2.1.min.js"></script> 10 <!-- bootstrap --> 11 <link rel="stylesheet" href="./plugIns/bootstrap-3.3.7/css/bootstrap.min.css"> 12 <script src="./plugIns/bootstrap-3.3.7/js/bootstrap.min.js" charset="utf-8"></script> 13 <!-- webuploader --> 14 <link rel="stylesheet" type="text/css" href="./plugIns/webuploader-0.1.5/webuploader.css"> 15 <script type="text/javascript" src="./plugIns/webuploader-0.1.5/webuploader.min.js"></script> 16 <!-- font-awesome --> 17 <link rel="stylesheet" href="./plugIns/font-awesome-4.7.0/css/font-awesome.min.css"> 18 <link rel="stylesheet" href="./css/filepreview/preview.css"> 19 </head> 20 21 <body> 22 <div class="container" style="padding-top:150px;"> 23 <div> 24 <div class="list"> 25 26 </div> 27 </div> 28 <div id="uploader" class="wu-example"> 29 <!--Used to store file information--> 30 <div id="thelist" class="uploader-list"></div> 31 <div class="btns"> 32 <div id="picker">Select file</div> 33 <button id="ctlBtn" class="btn btn-default">Start uploading</button> 34 </div> 35 </div> 36 </div> 37 <div class="load"> 38 <img src="./images/loading.gif" alt=""> 39 </div> 40 </body> 41 <script src="./js/filepreview/preview.js" charset="utf-8"></script> 42 <script src="./js/filepreview/upload.js" charset="utf-8"></script> 43 </html>
2. upload.js to control file upload
1 $(function() { 2 var $list = $('#thelist'), 3 $btn = $('#ctlBtn'), 4 state = 'pending'; 5 var uploader = WebUploader.create({ 6 // swf File path 7 swf: './plugIns/webuploader-0.1.5/Uploader.swf', 8 // File receiving server. 9 server: '/file/upload', 10 // Select the button for the file. Optional. 11 // Internal based on current operation is created, possibly input Elements, or possibly flash. 12 pick: '#picker', 13 // Uncompressed image, By default, if yes jpeg,File upload will be compressed before upload! 14 resize: false, 15 // Start to upload fragments. 16 chunked: true, 17 //fileSingleSizeLimit: 10*1024*1024,//Limit size 10M, single file 18 //fileSizeLimit: allMaxSize*1024*1024,//Limit size 10M, all selected files, beyond the selection 19 //Set the type of file allowed to upload, but clicking on the file will be very stuck. 20 // accept: { 21 // title: 'Images', 22 // extensions: 'jpg,png', 23 // mimeTypes: 'image/*' 24 // } 25 }); 26 // When files are added to the queue 27 uploader.on('fileQueued', function(file) { 28 let typeList = ['png', 'jpg', 'txt', 'xls', 'doc', 'ppt', 'pdf', 'mp4','docx','pptx','xlsx']; 29 if(!typeList.includes(file.name.split('.')[1])){ 30 alert("Unsupported file types!"); 31 uploader.removeFile( file ); 32 return; 33 } 34 35 36 $list.append('<div id="' + file.id + '" class="item">' + 37 '<h4 class="info">' + file.name + '</h4>' + 38 '<p class="state">Waiting for uploading...</p>' + 39 '</div>'); 40 }); 41 // Create progress bar to display in real time during file upload. 42 uploader.on('uploadProgress', function(file, percentage) { 43 var $li = $('#' + file.id), 44 $percent = $li.find('.progress .progress-bar'); 45 46 // Avoid duplicate creation 47 if (!$percent.length) { 48 $percent = $('<div class="progress progress-striped active">' + 49 '<div class="progress-bar" role="progressbar" style="width: 0%">' + 50 '</div>' + 51 '</div>').appendTo($li).find('.progress-bar'); 52 } 53 54 $li.find('p.state').text('Uploading'); 55 56 $percent.css('width', percentage * 100 + '%'); 57 }); 58 uploader.on('uploadSuccess', function(file) { 59 getFileList(); 60 $('#' + file.id).find('p.state').text('Uploaded'); 61 }); 62 63 uploader.on('uploadError', function(file) { 64 $('#' + file.id).find('p.state').text('Upload error'); 65 }); 66 67 uploader.on('uploadComplete', function(file) { 68 $('#' + file.id).find('.progress').fadeOut(); 69 }); 70 71 uploader.on('all', function(type) { 72 if (type === 'startUpload') { 73 state = 'uploading'; 74 } else if (type === 'stopUpload') { 75 state = 'paused'; 76 } else if (type === 'uploadFinished') { 77 state = 'done'; 78 } 79 80 if (state === 'uploading') { 81 $btn.text('Suspend upload'); 82 } else { 83 $btn.text('Start uploading'); 84 } 85 }); 86 87 $btn.on('click', function() { 88 if (state === 'uploading') { 89 uploader.stop(); 90 } else { 91 uploader.upload(); 92 } 93 }); 94 });
3. preview.js for preview
1 $(function() { 2 const typeList = ['png', 'jpg', 'txt', 'xls', 'doc', 'ppt', 'pdf','docx','pptx','xlsx']; 3 getFileList = function() { 4 $(".list").empty(); 5 $.get("/file/list", function(data) { 6 data = JSON.parse(data); 7 for (let file of data) { 8 let htmlStr = '<a class="point file" data-file="' + file.name + '" data-size="' + file.size + '" data-type="'+ file.type +'">'; 9 if (file.type.toLowerCase() == 'png' || file.type.toLowerCase() == 'jpg') { 10 htmlStr = '<a class="file" target="_blank" href="./filelist/' + file.name + '">'; 11 } else if (file.type.toLowerCase() == 'pdf') { 12 htmlStr = '<a class="file" target="_blank" href="http://localhost:8080/plugIns/pdfjs/web/viewer.html?file=../../../../filelist/' + file.name + '">'; 13 } else if (file.type.toLowerCase() == 'mp4') { 14 htmlStr = '<a class="file" target="_blank" href="video?path=../../filelist/' + file.name + '">'; 15 } 16 let imgName = file.type=='docx'||file.type=='xlsx'||file.type=='pptx'?file.type.substr(0,file.type.length-1):file.type; 17 $(".list").append( 18 '<div class="col-xs-6 col-md-2">' + htmlStr + 19 '<embed src="./images/svg/' + imgName + '.svg" type="image/svg+xml" /><span>' + file.name + 20 '</span></a> <i class="fa fa-eye"></i> <span class="number">'+file.number+'</span></div>' 21 ); 22 } 23 }); 24 } 25 getFileList(); 26 27 /** 28 * Files that cannot be viewed directly need to be converted by server first 29 */ 30 $(".list").on("click", ".point", function() { 31 let date = new Date().getTime(); 32 let param = $(this).data("file"); 33 let type = $(this).data("type"); 34 if (typeList.indexOf(type)==-1) { 35 alert("Preview file type is not supported at this time!"); 36 return; 37 } 38 if ($(this).data("size") >= 11534336) { 39 alert("The file is too large to support preview for the time being!"); 40 return; 41 } 42 $('.load').addClass('active'); 43 $.ajax({ 44 type: 'post', 45 url: '/file/preview', 46 data: param, 47 contentType: 'application/json', 48 dataType: 'text', 49 success: function(data) { 50 $('.load').removeClass('active'); 51 console.log("Conversion time consuming===>" + (new Date().getTime() - date) + "ms"); 52 window.open("http://localhost:8080/plugIns/pdfjs/web/viewer.html?file=../../../../filelist/temp/" + data + ".pdf"); 53 }, 54 error: function(error) { 55 $('.load').removeClass('active'); 56 alert("error!"); 57 } 58 }); 59 }); 60 61 /** 62 * View files, cumulative browsing 63 */ 64 $(".list").on("click", ".file", function() { 65 let nSpan = $(this).parent().find('.number'); 66 nSpan.text(nSpan.text()/1+1); 67 }); 68 });
4. Play mp4 video.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <meta http-equiv="X-UA-Compatible" content="ie=edge"> 8 <title></title> 9 <link rel="stylesheet" href="/plugIns/video-js-6.2.5/video-js.min.css"> 10 <!-- If you'd like to support IE8 --> 11 <script src="/plugIns/jquery-3.2.1.min.js"></script> 12 <script src="/plugIns/video-js-6.2.5/ie8/videojs-ie8.min.js" charset="utf-8"></script> 13 <script src="/Global.js" charset="utf-8"></script> 14 <style media="screen"> 15 .videoCont { 16 padding-top: 150px; 17 } 18 </style> 19 </head> 20 21 <body> 22 <div class="videoCont"> 23 <video id="my-video" class="video-js" controls preload="auto" width="720" height="480" poster="MY_VIDEO_POSTER.jpg" data-setup="{}"> 24 <source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4"> 25 <!-- <source src="http://vjs.zencdn.net/v/oceans.webm" type="video/webm"> 26 <source src="/filelist/Wildlife.wmv" type="video/wmv"> --> 27 <p class="vjs-no-js"> 28 To view this video please enable JavaScript, and consider upgrading to a web browser that 29 <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a> 30 </p> 31 </video> 32 </div> 33 <script src="/plugIns/video-js-6.2.5/video.min.js" charset="utf-8"></script> 34 <script type="text/javascript"> 35 let wWidth = document.body.clientWidth; 36 $('.videoCont').css('padding-left',(wWidth-$('#my-video').attr("width"))/2); 37 let path = Global.getParamByKey("path"); 38 $("#my-video source[type='video/mp4']").attr("src",path); 39 var myPlayer = videojs('my-video'); 40 videojs("my-video").ready(function() { 41 var myPlayer = this; 42 myPlayer.play(); 43 }); 44 </script> 45 </body> 46 47 </html>
5.pom.xml
1 <dependencies> 2 <!-- Spring Boot web rely on --> 3 <dependency> 4 <groupId>org.springframework.boot</groupId> 5 <artifactId>spring-boot-starter-web</artifactId> 6 </dependency> 7 8 <!-- Junit --> 9 <dependency> 10 <groupId>junit</groupId> 11 <artifactId>junit</artifactId> 12 <version>4.12</version> 13 </dependency> 14 <dependency> 15 <groupId>org.apache.commons</groupId> 16 <artifactId>commons-lang3</artifactId> 17 <version>3.6</version> 18 </dependency> 19 <!-- openoffice --> 20 <dependency> 21 <groupId>org.quartz-scheduler</groupId> 22 <artifactId>quartz</artifactId> 23 <version>2.3.0</version> 24 </dependency> 25 <!-- No support for post-03 office --> 26 <dependency> 27 <groupId>com.artofsolving</groupId> 28 <artifactId>jodconverter</artifactId> 29 <version>2.2.1</version> 30 </dependency> 31 <!-- Supporting post-03 office --> 32 <dependency> 33 <groupId>org.artofsolving.jodconverter</groupId> 34 <artifactId>jodconverter-core</artifactId> 35 <version>3.0-beta-4</version> 36 </dependency> 37 <dependency> 38 <groupId>org.openoffice</groupId> 39 <artifactId>jurt</artifactId> 40 <version>3.0.1</version> 41 </dependency> 42 <dependency> 43 <groupId>org.openoffice</groupId> 44 <artifactId>ridl</artifactId> 45 <version>3.0.1</version> 46 </dependency> 47 <dependency> 48 <groupId>org.openoffice</groupId> 49 <artifactId>juh</artifactId> 50 <version>3.0.1</version> 51 </dependency> 52 <dependency> 53 <groupId>org.openoffice</groupId> 54 <artifactId>unoil</artifactId> 55 <version>3.0.1</version> 56 </dependency> 57 58 <!--jodconverter2.2.1 Must rely on slf4j-jdk14 Must be this version, otherwise the log in the source code will be wrong, very low A Problem --> 59 <dependency> 60 <groupId>org.slf4j</groupId> 61 <artifactId>slf4j-jdk14</artifactId> 62 <version>1.4.3</version> 63 </dependency> 64 65 <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> 66 <dependency> 67 <groupId>com.alibaba</groupId> 68 <artifactId>fastjson</artifactId> 69 <version>1.2.35</version> 70 </dependency> 71 72 <dependency> 73 <groupId>commons-fileupload</groupId> 74 <artifactId>commons-fileupload</artifactId> 75 <version>1.3.1</version> 76 </dependency> 77 </dependencies>
6. Tool class Office 2PdfUtil for document conversion to pdf format
1 package org.spring.springboot.util; 2 3 import java.io.File; 4 import java.util.regex.Pattern; 5 6 import org.artofsolving.jodconverter.OfficeDocumentConverter; 7 import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration; 8 import org.artofsolving.jodconverter.office.OfficeManager; 9 10 public class Office2PdfUtil { 11 12 private static Office2PdfUtil office2PdfUtil = new Office2PdfUtil(); 13 private static OfficeManager officeManager; 14 // Service port 15 private static int OPEN_OFFICE_PORT[] = { 8100, 8101, 8102, 8103 }; 16 17 public static Office2PdfUtil getOffice2PdfUtil() { 18 return office2PdfUtil; 19 } 20 21 /** 22 * 23 * office2Pdf Method 24 * 25 * @descript: TODO 26 * @param inputFile 27 * File full path 28 * @param pdfFilePath 29 * pdf File full path 30 * @return void 31 */ 32 public static void office2Pdf(File inputFile, File pdfFile) { 33 34 try { 35 // Open service 36 startService(); 37 OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager); 38 // Start conversion 39 converter.convert(inputFile, pdfFile); 40 // Close 41 stopService(); 42 System.out.println("End of operation"); 43 } catch (Exception e) { 44 // TODO: handle exception 45 e.printStackTrace(); 46 } 47 } 48 49 public static void stopService() { 50 if (officeManager != null) { 51 officeManager.stop(); 52 } 53 } 54 55 public static void startService() { 56 DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); 57 try { 58 configuration.setOfficeHome(getOfficeHome());// Setting up installation directory 59 configuration.setPortNumbers(OPEN_OFFICE_PORT); // Set port 60 configuration.setTaskExecutionTimeout(1000 * 60 * 5L); 61 configuration.setTaskQueueTimeout(1000 * 60 * 60 * 24L); 62 officeManager = configuration.buildOfficeManager(); 63 officeManager.start(); // Startup service 64 } catch (Exception ce) { 65 System.out.println("office Transform service startup failure!detailed information:" + ce); 66 } 67 } 68 69 /** 70 * openoffice Installation path 71 * 72 * @return 73 */ 74 public static String getOfficeHome() { 75 String osName = System.getProperty("os.name"); 76 if (Pattern.matches("Linux.*", osName)) { 77 return "/opt/openoffice.org3"; 78 } else if (Pattern.matches("Windows.*", osName)) { 79 return "C:/Program Files (x86)/OpenOffice 4/"; 80 } else if (Pattern.matches("Mac.*", osName)) { 81 return "/Application/OpenOffice.org.app/Contents"; 82 } 83 return null; 84 } 85 }
It is important to note that there is no need to manually open the open office in the system, and the above code will automatically open when it runs.
Private static int OPEN_OFFICE_PORT[]= {8100, 8101, 8102, 8103}; this is the port of openoffice, default is 8100, written to open multiple OpenOffice services, to speed up the efficiency of multi-threaded conversion.
7. Interface class FileController
1 package org.spring.springboot.web; 2 3 import java.io.File; 4 import java.io.IOException; 5 import java.util.ArrayList; 6 import java.util.Iterator; 7 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 import org.spring.springboot.bean.FileBean; 12 import org.spring.springboot.util.Office2PdfUtil; 13 import org.springframework.web.bind.annotation.GetMapping; 14 import org.springframework.web.bind.annotation.PostMapping; 15 import org.springframework.web.bind.annotation.RequestBody; 16 import org.springframework.web.bind.annotation.RequestMapping; 17 import org.springframework.web.bind.annotation.RestController; 18 import org.springframework.web.multipart.MultipartFile; 19 import org.springframework.web.multipart.MultipartHttpServletRequest; 20 import org.springframework.web.multipart.commons.CommonsMultipartResolver; 21 22 import com.alibaba.fastjson.JSON; 23 24 25 @RestController 26 @RequestMapping("file") 27 public class FileController { 28 29 @GetMapping("list") 30 public String getFileList() { 31 return getFileName(); 32 } 33 34 public static String getFileName() { 35 String path = System.getProperty("user.dir") + "\\src\\main\\resources\\static\\filelist"; // Route 36 File f = new File(path); 37 if (!f.exists()) { 38 System.out.println(path + " not exists"); 39 return null; 40 } 41 42 ArrayList<FileBean> files = new ArrayList<>(); 43 44 File fa[] = f.listFiles(); 45 for (File fs : fa) { 46 if (fs.isFile()) { 47 FileBean fb = new FileBean(fs.getName(), fs.getName().split("\\.")[1], String.valueOf(fs.length())); 48 files.add(fb); 49 } 50 } 51 return JSON.toJSONString(files); 52 } 53 54 @PostMapping(value = "preview", produces = "application/json; charset=utf-8") 55 public String getPreview(@RequestBody String fileName) throws IOException { 56 String sysDir = System.getProperty("user.dir") + "\\src\\main\\resources\\static\\filelist\\"; 57 File inputFile = new File(sysDir + fileName); 58 String outputPath = sysDir + "temp"; 59 File temp = new File(outputPath); 60 // Directory does not exist, create directory 61 if (!temp.exists()) { 62 temp.mkdir(); 63 } 64 File outputFile = new File( 65 outputPath + "\\" + fileName.split("\\.")[0] + "_" + fileName.split("\\.")[1] + ".pdf"); 66 // If the converted file already exists, there is no need to convert it again. 67 if (outputFile.exists()) { 68 return fileName.split("\\.")[0]+ "_" + fileName.split("\\.")[1]; 69 } 70 //Method 1: Use com.artofsolving 71 //OpenOfficeUtil.office2Pdf(inputFile, outputFile); 72 //Method 2: org.artofsolving 73 Office2PdfUtil.office2Pdf(inputFile, outputFile); 74 return fileName.split("\\.")[0]+ "_" + fileName.split("\\.")[1]; 75 } 76 77 @RequestMapping("/upload") 78 public String upload2(HttpServletRequest request, HttpServletResponse response) 79 throws IllegalStateException, IOException { 80 // Create a springmvc Upload file parser 81 CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(); 82 // judge request Is there a file upload?,That is, multi-part requests 83 if (multipartResolver.isMultipart(request)) { 84 // Converting to multipart request 85 MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; 86 // Obtain request All filenames in 87 Iterator<String> iter = multiRequest.getFileNames(); 88 while (iter.hasNext()) { 89 // Record the start time of the upload process to calculate the upload time 90 int pre = (int) System.currentTimeMillis(); 91 // Obtain uploaded files 92 MultipartFile file = multiRequest.getFile(iter.next()); 93 if (file != null) { 94 // Gets the name of the file currently Uploaded 95 String myFileName = file.getOriginalFilename(); 96 // If the name is not "",Explain that the file exists or that it does not exist 97 if (myFileName.trim() != "") { 98 System.out.println(myFileName); 99 // Rename the uploaded file name 100 // String fileName = "demoUpload" + file.getOriginalFilename(); 101 // Define the upload path 102 String path = System.getProperty("user.dir") + "\\src\\main\\resources\\static\\filelist\\" 103 + myFileName; 104 File localFile = new File(path); 105 try { 106 file.transferTo(localFile); 107 } catch (IOException e) { 108 e.printStackTrace(); 109 } 110 } 111 } 112 // Record the time after uploading the file 113 int finaltime = (int) System.currentTimeMillis(); 114 System.out.println(finaltime - pre); 115 } 116 } 117 return "/success"; 118 } 119 }
8. The last one has nothing to do with Demo. It's a test of multithreaded pdf conversion.
1 package org.spring.springboot; 2 3 import java.io.File; 4 import java.net.ConnectException; 5 import java.util.concurrent.CountDownLatch; 6 7 import org.spring.springboot.util.Office2PdfUtil; 8 import org.spring.springboot.util.OpenOfficeUtil; 9 10 public class Main extends Thread { 11 private int index; 12 private CountDownLatch latch; 13 14 public Main(int index, CountDownLatch latch) { 15 this.index = index; 16 this.latch = latch; 17 } 18 19 @Override 20 public void run() { 21 super.run(); 22 String str = String.format("5m_%s.doc", index); 23 long time = System.currentTimeMillis(); 24 work(str); 25 latch.countDown(); 26 System.out.println(String.format("file%s Analytical time-consuming:%sms", str, String.valueOf(System.currentTimeMillis() - time))); 27 } 28 29 public static void main(String[] args) { 30 CountDownLatch latch = new CountDownLatch(50); 31 Office2PdfUtil.startService(); 32 for (int i = 1; i < 51; i++) { 33 new Main(i, latch).start(); 34 } 35 try { 36 long time = System.currentTimeMillis(); 37 System.out.println(String.format("start")); 38 latch.await(); 39 Office2PdfUtil.stopService(); 40 System.out.println(String.format("All file parsing takes time:%sms", String.valueOf(System.currentTimeMillis() - time))); 41 } catch (InterruptedException e) { 42 // TODO Auto-generated catch block 43 e.printStackTrace(); 44 } 45 } 46 47 public static void work(String fileName) { 48 String sysDir = System.getProperty("user.dir") + "\\src\\main\\resources\\static\\test\\"; 49 File inputFile = new File(sysDir + fileName); 50 String outputPath = sysDir + "temp"; 51 File outputFile = new File( 52 outputPath + "\\" + fileName.split("\\.")[0] + "_" + fileName.split("\\.")[1] + ".pdf"); 53 Office2PdfUtil.office2Pdf(inputFile, outputFile); 54 } 55 56 }
CountDownLatch can monitor the end of multithreading. Lines 30 and 32 set the number of parsed files.
9.python generates multiple content file codes and submits them as well.
1 #-*-coding:utf-8-*- 2 def gen_file(path,size): 3 #First, take the path path Create a new file and set the mode to write 4 file = open(path,'w') 5 #Depending on file size, offset file read location 6 file.seek(1024*1024*size)#Tentatively MB As a unit. 7 #Then write anything in the current location, you must write it, otherwise the file will not be so big. 8 file.write('\x00') 9 file.close() 10 11 12 13 for i in range(100): 14 gen_file('E:/5m_'+str(i+1)+'.doc',5)
All of the above are test codes, which should be approved in the project. It's all about taking notes so that you don't have to look around again next time.
Four, page
There are a lot of pits in it, but I think the main reason lies in the pdf conversion step:
1.jodconverter-core 3.0-beta-4 This package's maven dependency does not seem to be downloadable
2.com.artofsolution.jodconverter and org.artofsolution.jodconverter are silly and confusing packages
3.openoffice is free. You know, conversion efficiency is not complimentary, slow, and concurrent support is not good.
4. Convert dozens of files in the words of com.artofsolving.jodconverter, and there is no regular card holding, waiting for half an hour, there is still no response, you have to kill the openoffice process to come back, try many times, org.artofsolving.jodconverter did not find this problem.
5. Open office service and close open office service only need to be invoked once when multiple document transformations occur. Otherwise, it's very silent to turn on and off every time.