整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JAVA實現在線查看PDF和office文檔,一個很

          JAVA實現在線查看PDF和office文檔,一個很多人都踩坑的問題

          天我來說說這個不怎么被人提起,卻又是很多人沒搞定的問題!

          一個項目中要做一個在線預覽附件(和百度文庫差不多)的小功能點,我在開發過程中踩了很多坑的同時也總結了一些方法,僅供廣大猿友參考,那么要實現這個小功能,目前主要是有如下3種可行的實現方式,下面先說實現的思路設計與他們的優缺點:

          第一種思路:先把附件office文檔(doc,docx,ppt,pptx,xls,xlsx,txt)轉為PDF格式,這里需要用一個OpenOffic這玩意來轉換,有服務和端口的屬性,所以它是一個服務類軟件(像tomcat這類,區別是所提供的服務各不相同),然后把PDF轉為SWF文件類型,最后在前臺頁面使用Flexpaper插件進行播放即可實現。

          第一種方式的好處在于:可以兼容IE低版本的瀏覽器。

          第一種方式的!好在于:

          首先是把一個附件進行了2次的轉換,這里的轉換是指另外保存了.pdf和.swf這兩種格式的文件,這無疑的加大了存儲空間的使用。

          其次是.swf格式的文件需要放到項目的WebRoot文件夾的下層才能被Flexpaper插件所讀取,當然了你也可以使用Nginx做一個地址映射,把.swf文件放到別的地方也能被Flexpaper所讀取。

          最后這種方式最大的缺點是Flexpaper插件主要是依賴于一個文件FlexPaperViewer.swf,而這個文件是無法編輯的,如果要編輯,則要找到Flexpaper的源碼,然后修改源碼,在重新構建生成FlexPaperViewer.swf,來著這里,大家肯定會問,為什么要編輯這個文件,那是因為這個文件是控制Flexpaper插件的各種按鈕的,比如打印按鈕的顯示和隱藏,更重要的是Flexpaper插件是有它自帶的LOGO水印,不去掉會顯得很難看且尷尬,而編輯這個文件可以解決這些問題,另外如果你的功能中要對附件加自定義的水印的話,就不要采取這種方式了,因為是不可能實現的,原因很簡單,因為PDF轉SWF中這一步是很坑的,即使你的PDF中已經添加了水印,但是轉換后得到的SWF是無水印的,不知道為什么會幫你自動去掉,所以前臺讀取的是.swf就自然就顯示不出來水印了。

          谷歌瀏覽器需要安裝flash插件才能正常顯示。

          第二種思路:第一步還是和第一種一樣的,都是先把附件為office文檔轉換為PDF格式,但是不同于第一種的是得到PDF之后呢,是使用pdf2htmlex插件把PDF直接轉化為HTML文本輸出到頁面來。

          第一種方式的好處在于:就是不用生成.swf文件,節省空間,提升效率。

          第一種方式的!好在于:

          首先只能達到附件預覽的效果,如果你要實現打印,文本搜索等功能是是要自己另外寫代碼的。

          其次,如果你的PDF中加了水印的話,輸出的HTML也是沒有水印的。

          第三種思路:最靠譜的一種方式,第一步和前兩種方法是一樣的,都是先把附件Office文檔轉換了PDF格式,然后不同的是,得到PDF之后,使用PDF.JS這個框架來顯示附件,但是這個框架是基于HTML5的新特性才能實現的,IE的話需要9以上版本才能兼容,這是最大的缺點了,優點太多了,即可看到水印,而且打印等這些功能點都已經實現好了,并且可以改變一些參數就可以實現這些按鈕的權限的控制,良心之作。

          寫完思路之后當然要寫具體要怎么寫代碼,先說第一種:

          這是JAVA后臺代碼結構

          • 一個是測試類,是用來測試offiec文檔轉換換為PDF和SWF的
          • 一個工具類,是用來實現轉換的代碼
          • 一個配置文件是是配置你的OpenOffic服務的端口和地址

          這是Web前臺代碼結構

          主要是一些CSS和JS的控件和樣式,前臺的頁面主要是這個FlexPaperViewer.html 或者index.html把頁面嵌進一個DIV層就能自定義展示,要顯示的文檔要轉換為SWF格式放到WEBROOT下層任意路徑,比如我的docs文件夾里的Paper.pdf.swf文件

          效果如下

          項目Demo代碼百度云地址:這個項目的打印功能和水印是被我去掉的,具體的怎么去掉自己去百度吧很多教程很麻煩這里就不演示

          需要我總結的網盤鏈接的可以轉發+私信【源碼】獲取!

          保留了打印功能的是這個地址:里面有個FlexPaperViewer.swf的配置文件把它替換了原來的就行了

          需要我總結的網盤鏈接的可以私信【源碼】獲取!

          然后說第二種:

          通過調用工具類里邊的一個方法,把一個PDF文件內容變為靜態的HTML,然后瀏覽器直接顯示HTML就可以實現預覽效果了。

          效果如下

          Demo鏈接:需要我總結的網盤鏈接的可以轉發+私信【源碼】獲取!

          最后說第三種:

          首先呢要在TOMCAT服務器搭建一個PDF.JS框架,說白了就是在webapp文件夾放入一個已經搭建好的小項目,如圖

          然后如何調用呢?在你的項目中DIV的SRC或者彈框中用

          src=http://localhost:8080/generic/web/viewer.html?file=http://localhost:8080/resources/PDF文件名 其中resources是個文件夾這個是自己建的就可以了,?后邊PDF文件的路徑

          效果如下

          百度云:需要鏈接的可以轉發+私信【源碼】獲取! 這個是PDF.JS框架代碼

          最后附上PDF加水印的代碼,也用到一些第三方jar包,直接調用,比較簡單。

          鏈接:需要我總結的網盤鏈接的可以轉發+私信【源碼】獲取!

          最后補充說明一下:

          關于把offer文檔轉換為PDF的時候首先在本機安裝OpenOffice,然后就開啟服務,在安裝目錄下的program文件夾(里邊是存命令的),進入后 通過cmd控制臺輸入以下命令:

          soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard

          注本頭條號,專注做前端

          今天要分享的是基于html5,通過強大的JS實現的在線pdf閱讀器,大部分瀏覽器支持pdf閱讀,但是有的瀏覽器不支持,可以通過pdf.js來解決

          //

          DFium[1] 是 Chromium 的 PDF 渲染引擎,許可協議為 BSD 3-Clause。不同于 Mozilla 基于 HTML5 的 PDF.js[2],PDFium 是基于 Foxit Software (福昕軟件)的渲染代碼,Google 與其合作開源出的。

          此外,Qt PDF 模塊也選用了 PDFium ,可見 QtWebEngine / QtPdf[3]

          本文將介紹如何用 PDFium 實現一個簡單的 PDF 閱讀器,代碼見:https://github.com/ikuokuo/pdfium-reader 。

          編譯 PDFium

          使用預編譯庫:https://github.com/bblanchon/pdfium-binaries

          不然,參考 PDFium / README[4] 自己編譯,實踐步驟如下:

          # get depot_tools, contains: gclient, ninja, gn, ...
          git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
          export PATH="$PATH:$HOME/Codes/Star/depot_tools"
          
          # get pdfium
          cd pdfium-reader/
          mkdir -p third_party/chromium
          cd third_party/chromium
          gclient config --unmanaged https://pdfium.googlesource.com/pdfium.git
          gclient sync
          cd pdfium
          
          # get deps
          #  on linux, install additional build dependencies
          ./build/install-build-deps.sh
          
          # gn config
          #  args see the following `out/Release/args.gn`
          gn args out/Release
          
          # ninja build
          #  pdfium
          ninja -C out/Release pdfium
          #  pdfium_test
          ninja -C out/Release pdfium_test
          
          # run sample: pdf > ppm
          ./out/Release/pdfium_test --ppm path/to/myfile.pdf
          

          期間 out/Release/args.gn 內容如下:

          use_goma=false  # Googlers only. Make sure goma is installed and running first.
          is_debug=false  # Enable debugging features.
          
          # Set true to enable experimental Skia backend.
          pdf_use_skia=false
          # Set true to enable experimental Skia backend (paths only).
          pdf_use_skia_paths=false
          
          pdf_enable_xfa=false  # Set false to remove XFA support (implies JS support).
          pdf_enable_v8=false  # Set false to remove Javascript support.
          pdf_is_standalone=true  # Set for a non-embedded build.
          pdf_is_complete_lib=true  # Set for a static library build.
          is_component_build=false  # Disable component build (Though it should work)
          

          使用 PDFium

          閱讀 PDFium / Getting Started[5],了解如何初始化 PDFium 及載入文檔。步驟如下,或見 pdfium_start.c[6]:

          #include <fpdfview.h>
          #include <stdio.h>
          
          int main(int argc, char const *argv[]) {
            FPDF_STRING test_doc="test_doc.pdf";
            if (argc >=2) {
              test_doc=argv[1];
            }
            printf("test_doc: %s\n", test_doc);
          
            FPDF_InitLibrary();
          
            FPDF_DOCUMENT doc=FPDF_LoadDocument(test_doc, NULL);
            if (!doc) {
              unsigned long err=FPDF_GetLastError();
              // Load pdf docs unsuccessful: ...
              goto EXIT;
            }
          
            FPDF_CloseDocument(doc);
          EXIT:
            FPDF_DestroyLibrary();
            return 0;
          }
          

          獲取信息

          樣例見 pdf_info.cc[7],可打印 PDF 元數據、頁面信息等。

          FPDF_GetMetaText 獲取元數據(UTF-16LE 編碼):

          void PrintPdfMetaData(FPDF_DOCUMENT doc) {
            static constexpr const char *kMetaTags[]={
                "Title",   "Author",   "Subject",      "Keywords",
                "Creator", "Producer", "CreationDate", "ModDate"};
            for (const char *meta_tag : kMetaTags) {
              const unsigned long len=FPDF_GetMetaText(doc, meta_tag, nullptr, 0);
              if (!len)
                continue;
          
              std::vector<char16_t> buf(len);
              FPDF_GetMetaText(doc, meta_tag, buf.data(), buf.size());
              auto text=strings::FromUtf16(std::u16string(buf.data()));
              if (strcmp(meta_tag, "CreationDate")==0 ||
                  strcmp(meta_tag, "ModDate")==0) {
                text=fpdf::DateToRFC3399(text);
              }
              std::cout << " " << meta_tag << ": " << text << std::endl;
            }
          }
          

          渲染頁面

          樣例見 pdf_render.cc[8],可渲染 PDF 頁面并保存為 PNG。

          FPDF_RenderPageBitmap 渲染某一頁:

          void PdfRenderPage(const std::string &pdf_name, FPDF_DOCUMENT doc, int index) {
            Timer t;
          
            FPDF_PAGE page=FPDF_LoadPage(doc, index);
          
            double scale=1.0;
            // double scale=2.0;
            int width=static_cast<int>(FPDF_GetPageWidth(page) * scale);
            int height=static_cast<int>(FPDF_GetPageHeight(page) * scale);
            int alpha=FPDFPage_HasTransparency(page) ? 1 : 0;
            ScopedFPDFBitmap bitmap(FPDFBitmap_Create(width, height, alpha));  // BGRx
          
            if (bitmap) {
              FPDF_DWORD fill_color=alpha ? 0x00000000 : 0xFFFFFFFF;
              FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, fill_color);
          
              int rotation=0;
              int flags=FPDF_ANNOT;
              FPDF_RenderPageBitmap(bitmap.get(), page, 0, 0, width, height,
                  rotation, flags);
              auto t_render=t.Elapsed();
          
              int stride=FPDFBitmap_GetStride(bitmap.get());
              void *buffer=FPDFBitmap_GetBuffer(bitmap.get());
          
              char img_name[256];
              int chars_formatted=snprintf(
                  img_name, sizeof(img_name), "%s.%d.png", pdf_name.c_str(), index);
              if (chars_formatted < 0 ||
                  static_cast<size_t>(chars_formatted) >=sizeof(img_name)) {
                fprintf(stderr, "Filename is too long: %s\n", img_name);
                exit(EXIT_FAILURE);
              }
          
              auto ok=PdfWritePng(img_name, buffer, width, height, stride);
              if (!ok) {
                fprintf(stderr, "Write png failed: %s\n", img_name);
                exit(EXIT_FAILURE);
              }
              auto t_write=t.Elapsed();
          
              fprintf(stdout, "%s\n", img_name);
              fprintf(stdout, " %02d: %dx%d, render=%lldms, write=%lldms\n",
                  index, width, height, t_render, t_write);
            } else {
              fprintf(stderr, "Page was too large to be rendered.\n");
              exit(EXIT_FAILURE);
            }
          
            FPDF_ClosePage(page);
          }
          

          stb_image_write.h[9] 存為 PNG:

          bool PdfWritePng(const std::string &img_name, void *buffer,
                           int width, int height, int stride) {
            // BGRA > RGBA
            auto buf=reinterpret_cast<uint8_t *>(buffer);
            for (int r=0; r < height; ++r) {
              for (int c=0; c < width; ++c) {
                auto pixel=buf + (r*stride) + (c*4);
                auto b=pixel[0];
                pixel[0]=pixel[2];  // b=r
                pixel[2]=b;         // r=b
              }
            }
            return stbi_write_png(img_name.c_str(), width, height, 4, buf, stride) !=0;
          }
          

          實現 UI

          本文給出的 PDFium Reader[10] 代碼,用的 ImGui[11]+GLFW[12]+OpenGL3[13] 實現的 UI,可跨三大桌面系統。

          想進一步了解的,可以直接看代碼,編譯運行依照 README。

          腳注

          [1] PDFium: https://pdfium.googlesource.com/pdfium/

          [2] PDF.js: https://github.com/mozilla/pdf.js

          [3] QtWebEngine / QtPdf: https://code.qt.io/cgit/qt/qtwebengine.git/tree/src

          [4] PDFium / README: https://pdfium.googlesource.com/pdfium/

          [5] PDFium / Getting Started: https://pdfium.googlesource.com/pdfium/+/refs/heads/main/docs/getting-started.md

          [6] pdfium_start.c: https://github.com/ikuokuo/pdfium-reader/blob/main/samples/pdfium_start.c

          [7] pdf_info.cc: https://github.com/ikuokuo/pdfium-reader/blob/main/samples/pdf/pdf_info.cc

          [8] pdf_render.cc: https://github.com/ikuokuo/pdfium-reader/blob/main/samples/pdf/pdf_render.cc

          [9] stb_image_write.h: https://github.com/nothings/stb/blob/master/stb_image_write.h

          [10] PDFium Reader: https://github.com/ikuokuo/pdfium-reader

          [11] ImGui: https://github.com/ocornut/imgui

          [12] GLFW: https://github.com/glfw/glfw

          [13] OpenGL3: https://www.opengl.org/


          主站蜘蛛池模板: 精品一区二区三区免费毛片| 又硬又粗又大一区二区三区视频| 亚洲av永久无码一区二区三区| 久久久无码一区二区三区| 亚洲国产精品第一区二区| 伊人色综合一区二区三区影院视频 | 在线精品动漫一区二区无广告 | 一区二区三区国产精品| 日本一区二区三区精品国产 | 日韩精品一区二区三区视频| 国产91精品一区二区麻豆网站| 精品成人av一区二区三区| 99久久精品国产免看国产一区| 视频一区在线播放| 国产福利电影一区二区三区久久久久成人精品综合 | 亚洲日本一区二区一本一道| 亚洲福利秒拍一区二区| 国产精品伦一区二区三级视频| 一区二区三区无码高清| 女人和拘做受全程看视频日本综合a一区二区视频 | 亚洲日韩中文字幕一区| 亚洲av无码一区二区三区观看| 久久青草精品一区二区三区| 亚洲色精品vr一区二区三区 | 久久综合一区二区无码| 日本一区二区高清不卡| 国产精品自在拍一区二区不卡| 一区二区日韩国产精品| 亚洲片一区二区三区| 久久综合亚洲色一区二区三区| 日韩人妻精品一区二区三区视频| 97久久精品无码一区二区| 无码人妻精一区二区三区| 一区二区三区视频观看| 久久亚洲AV午夜福利精品一区| 国产精品福利一区二区| 一区二区三区无码高清视频| 亚洲熟妇av一区| 中文字幕日韩一区二区三区不 | 午夜一区二区免费视频| 韩国福利一区二区三区高清视频 |