Java檔案上傳資料庫(並儲存本地)、word轉pdf並進行頁面預覽
對於頁面預覽用到了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服務。
參考上一篇:
//檔案上傳資料庫臨時表 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();
}
}
以上整個邏輯完成,主要參考程式碼如上,部分工具類下篇展示。頁面如下: