1. 程式人生 > >Java檔案上傳資料庫(並儲存本地)、word轉pdf並進行頁面預覽

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服務。 參考上一篇:

OpenOffice註冊windows服務 下面進行具體說明: 1.匯入jar包:用gradle匯入+本地jar匯入: (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’]) 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();
        }
    }

以上整個邏輯完成,主要參考程式碼如上,部分工具類下篇展示。頁面如下: 在這裡插入圖片描述