对于页面预览用到了OpenOffice附件:
官方的下载地址:Apache OpenOffice
选择windows版本安装完成后,在cmd中执行下面两个命令,查看任务管理器中是否有soffice.bin的进程。(用到OpenOffice,必须保证任务管理器中有soffice.bin的进程)
cd C:\Program Files (x86)\OpenOffice 4\program
soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard
各别情况OpenOffice会杀掉自己的进程,所以也可以配置成Windows服务。
参考上一篇:OpenOffice注册windows服务
下面进行具体说明:
1.导入jar包:用gradle导入+本地jar导入:
gradle里配置如下:
(1.)OpenOffice转换jar:
compile(“org.jodconverter:jodconverter-core:4.2.0”)
compile(“org.openoffice:juh:4.1.2”)
compile(“org.openoffice:jurt:4.1.2”)
compile(“org.openoffice:ridl:4.1.2”)
compile(“org.openoffice:unoil:4.1.2”)
compile(“com.thoughtworks.xstream:xstream:1.4.10”)
//compile(“com.artofsolving:jodconverter:2.2.2”)
这些只需在gradle里写好依赖,直接远程下载包。
(2.)word文档转换pdf格式工具架包:jodconverter-2.2.2.jar
compile fileTree(dir:‘lib’,include:[’*.jar’])
解析:获取lib文件夹下所有jar包
jodconverter-2.2.2.jar下载:https://pan.baidu.com/s/1z0lWuX8spH8aVTo48NCVQw 密码:jndj
(找到lib文件夹下对应的jar)
这个远程下载如果有问题,就需要本地导入,在项目根路径下新建一个lib文件夹,将要导入的jar包拖进去,刷新gradle,显示下面图片表示成功。
2.文件上传数据库临时表(并保存本地)
a.建立临时表(log_file),存放文件信息。(这里用的表示之前项目用的,没做修改。)
b.建立对应实体类,Setter and Getter。
c.编写主要接口方法:
//文件上传数据库临时表
public LogFile upload(InputStream inputStream, String name, String fileType, String subType, String keyId, String fileSource, String userIdAndName) throws IOException;
d.编写实现类方法:
在程序中获取某个文件的绝对路径,@Value("${app.file.uploadPath:}")通过注解方式加载properties文件;在application.yml中配置文件路径,如图:
具体代码如下:
@Service
@Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
public class FileServiceImpl extends BaseService implements FileService {
@Value("${app.file.uploadPath:}")
private String uploadPath;
@Autowired
private LogFileDao logFileDao;
@Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public LogFile upload(InputStream inputStream, String name, String fileType, String subType, String keyId, String fileSource, String userIdAndName) throws IOException {
// TODO: inputStream不能多次读取,因此先读出来
// TODO: 下一步考虑是否从文件内容获取文件类型,而不是根据文件名
byte[] bytes = FileUtil.read(inputStream);
int fileSize = bytes.length;
String md5 = DigestUtils.md5Hex(bytes);
String sha1 = DigestUtils.sha1Hex(bytes);
Example example = new Example(LogFile.class);
example.createCriteria().andEqualTo("fileMd5", md5);
List<LogFile> list = logFileDao.selectByExample(example);
String sign = md5;
if (list != null) {
if(list.size() == 1){
// 存在md5相同的记录,需要判断sign
LogFile savedFile = list.get(0);
//判断服务器目录下是否有文件,数据库中有上传记录,但实际服务器目录无文件,读取文件时无法找到文件,无实际意义
File file = new File(savedFile.getFilePath()+savedFile.getFileName());
if (savedFile.getFileSha1() != null && savedFile.getFileSha1().equals(sha1) && savedFile.getFileSize() != null && savedFile.getFileSize() == fileSize) {
savedFile.setFilePath("******");
//如果文件不存在,可以上传文件
if(!file.exists()){
FileUtil.save(bytes, new FileOutputStream(savedFile.getFilePath()+savedFile.getFileName()));
}
return savedFile;
}
sign = md5 + sha1 + DigestUtils.md5Hex(String.valueOf(fileSize));
//如果出现多条的情况,直接清空表md5相同的日志记录,后面重新插入
}else{
logFileDao.deleteByExample(example);
}
}
String extName = name.substring(name.lastIndexOf(".") + 1);
String fileName = StringUtil.guid() + "." + extName;
String filePath = FileUtil.filePath(uploadPath);
// inputStream上面读取后,不能直接用
FileUtil.save(bytes, new FileOutputStream(filePath + fileName));
LogFile logFile = new LogFile();
logFile.setFileId(StringUtil.guid());
logFile.setFileType(fileType);
logFile.setSubType(subType);
logFile.setKeyId(keyId);
logFile.setFileName(fileName);
logFile.setOriginName(name);
logFile.setFilePath(filePath);
// fileDescribe
logFile.setExtName(extName);
// extType
logFile.setFileSize(fileSize);
// thumbName
logFile.setImageWidth(0);
logFile.setImageHeight(0);
logFile.setFileMd5(md5);
logFile.setFileSha1(sha1);
logFile.setFileSign(sign);
logFile.setFileSource(fileSource);
// deleteTime
// deleteUser
logFile.setFileState("0000");
// areaCode
// appCode
logFile.setManageTime(DateUtil.getDateDate());
logFile.setManageUser(userIdAndName);
//将文件信息插入log_file临时表
logFileDao.insert(logFile);
// 隐藏文件路径
logFile.setFilePath("******");
return logFile;
}
}
e.编写控制器类:
@RequestMapping(value="/upload", method = RequestMethod.POST)
public LogFile upload(@RequestParam(name = "name") String name, @RequestParam(name = "fileType", required = false) String fileType, @RequestParam(name = "subType", required = false) String subType,
@RequestParam(name = "keyId", required = false) String keyId, @RequestParam(name = "fileSource", required = false) String fileSource, HttpServletRequest httpServletRequest) throws IOException {
return fileService.upload(httpServletRequest.getInputStream(), name, fileType, subType, keyId, fileSource, super.getUserIdAndName());
}
以上文件上传逻辑完成:
e-1:整个逻辑应用了文件流,用MD5对fileId、filesign等进行加密。涉及了一个简单查询,一个删除接口上面没有完全体现。(每次上传文件是存到临时表,上传前会判断文件是否存在,如果出现多条的情况,直接清空表md5相同的日志记录,后面重新插入)
e-2:文件保存数据库同时,会在application.yml配置的文件路径下生成对应文件。
3.上传数据库表(并保存本地,与上同路径),word转pdf
a.建立数据库表Test
b.建立对应实体类,Setter and Getter。
c.编写主要接口方法:
//上传文件到数据库表
void worldImport(Test test);
d.编写接口实现类方法:
public class TestServiceImpl extends BaseService implements TestService{
@Autowired
private TestDao testDao;
@Override
public void worldImport(Test test) {
testDao.insertNotNull(test);
}
}
e.编写word转pdf工具类:
public class OpenOfficeUtil {
public static String wordToPDF(String filePath,String fileName){
File docFile = new File(filePath+fileName);
File pdfFile = null;
if (fileName.contains(".")){
pdfFile = new File(filePath+fileName.substring(0,fileName.indexOf("."))+"pdf.pdf");
}else {
pdfFile = new File(filePath+fileName+"pdf.pdf");
}
String pdfFilePath = pdfFile.getPath();
if (docFile.exists()){
if (!pdfFile.exists()){
OpenOfficeConnection connection = new SocketOpenOfficeConnection(8100);
try {
connection.connect();
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
converter.convert(docFile,pdfFile);
connection.disconnect();
} catch (ConnectException e) {
e.printStackTrace();
}
}else {
throw new RuntimeException("该文件已经转换过了!");
}
}else {
throw new RuntimeException("需要转换的文件不存在!");
}
return pdfFilePath;
}
}
f.编写控制器类:
@RequestMapping(value = "/worldImport",method = RequestMethod.POST)
public void worldImport(@RequestBody String fileSign) throws IOException, InvalidFormatException, SAXException {
if(StringUtils.isEmpty(fileSign)){
return;
}
LogFile logFile = fileService.selectBySign(fileSign);
if(logFile == null){
return;
}
//将Word文档转化为PDF文档
String pdfFilePath = OpenOfficeUtil.wordToPDF(logFile.getFilePath(),logFile.getFileName());
System.err.println(pdfFilePath);
FileInputStream fileInputStream = new FileInputStream(pdfFilePath);
byte[] content = new byte[fileInputStream.available()];
fileInputStream.read(content);
Test test = new Test();
test.setTest(content);
testServiceImpl.worldImport(test);
fileInputStream.close();
}
以上文件上传、word转pdf逻辑完成:
实现:通过调用临时表log_file信息(路径+名字),将需要转换的word文件转换成pdf文件,转格式存放在数据库表test中,同时在本地生成对应pdf文件。
4.对pdf文件进行预览
a.编写接口方法:
List<Test> world();
b.编写实现类方法:
@Override
public List<Test> world() {
return testDao.selectAll();
}
c.编写控制器类:
@RequestMapping(value = "/world",method = RequestMethod.GET)
public void world(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {
List<Test> tests = testServiceImpl.world();
//具体需求具体判断,此处获取的是数据库第六条数据的文件信息。
byte[] result = tests.get(7).getTest();
ServletOutputStream servletOutputStream = httpServletResponse.getOutputStream();
if (servletOutputStream != null && result != null){
httpServletResponse.setContentType("application/pdf");
httpServletResponse.setContentLength(result.length);
httpServletResponse.setHeader("Expires","0");
httpServletResponse.setHeader("Cache-Control","must-revalidate,post-check=0,pre-check=0");
httpServletResponse.setHeader("Pragma","public");
servletOutputStream.write(result);
servletOutputStream.flush();
servletOutputStream.close();
}
}
以上整个逻辑完成,主要参考代码如上,部分工具类下篇总结。页面展示如下: