1. 程式人生 > >html頁面儲存成圖片,圖片寫入pdf

html頁面儲存成圖片,圖片寫入pdf

需求是一個匯出pdf的功能,多方奔走終於實現了,走了不少彎路,而且懷疑現在這個方法仍是彎的。

有個jsPDF 外掛可以在前端直接生成pdf,很簡便,但不支援IE。

前端:

首先引入  html2canvas.js

html2canvas(document.body, {  //截圖物件
         //此處可配置詳細引數
         onrendered: function(canvas) {  //渲染完成回撥canvas
             canvas.id = "mycanvas";  
             // 生成base64圖片資料
             var dataUrl = canvas.toDataURL('image/png');   //指定格式,也可不帶引數
             var formData = new FormData();  //模擬表單物件
             formData.append("imgData", convertBase64UrlToBlob(dataUrl), "123.png"); //寫入資料
             var xhr = new XMLHttpRequest();  //資料傳輸方法
             xhr.open("POST", "../bulletin/exportPdf");  //配置傳輸方式及地址
             xhr.send(formData);
             xhr.onreadystatechange = function(){  //回撥函式
                 if(xhr.readyState == 4){
                        if (xhr.status == 200) {
                              var back = JSON.parse(xhr.responseText);
                              if(back.success == true){
                                 alertBox({content: 'Pdf匯出成功!',lock: true,drag: false,ok: true});
                              }else{
                                 alertBox({content: 'Pdf匯出失敗!',lock: true,drag: false,ok: true});
                              }
                        }
                  }
             };
         }
});
    
//將以base64的圖片url資料轉換為Blob
function convertBase64UrlToBlob(urlData){
    //去掉url的頭,並轉換為byte
    var bytes=window.atob(urlData.split(',')[1]);        
    //處理異常,將ascii碼小於0的轉換為大於0
    var ab = new ArrayBuffer(bytes.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < bytes.length; i++) {
        ia[i] = bytes.charCodeAt(i);
    }
    return new Blob( [ab] , {type : 'image/png'});
}

相容性:

Firefox 3.5+, Chrome, Opera, IE10+

不支援:iframe,瀏覽器外掛,Flash

跨域圖片需要在跨域伺服器header加上允許跨域請求

access-control-allow-origin: *  access-control-allow-credentials: true

svg圖片不能直接支援,已經有補丁包了,不過我沒有試過。

IE9不支援FormData資料格式,也不支援Blob,這種情況下將canvas生成的64base字串去掉url頭之後直接傳給後臺,後臺接收之後:

String base64 = Img.split(",")[1];
BASE64Decoder decode = new BASE64Decoder();
byte[] imgByte = decode.decodeBuffer(base64);

後端:

匯入 itext jar包

@RequestMapping("/exportPdf")
public @ResponseBody void exportPdf(MultipartHttpServletRequest request,HttpServletResponse response)throws ServletException, IOException {
    ResultData result = new ResultData();    //自定義結果格式
    String filePath = "c:\\exportPdf2.pdf";
    String imagePath = "c:\\exportImg2.bmp";
    Document document = new Document();
    try{
        Map getMap = request.getFileMap();
        MultipartFile mfile = (MultipartFile) getMap.get("imgData");  //獲取資料
        InputStream file = mfile.getInputStream();
        byte[] fileByte = FileCopyUtils.copyToByteArray(file);
            
        FileImageOutputStream imageOutput = new FileImageOutputStream(new File(imagePath));//開啟輸入流
        imageOutput.write(fileByte, 0, fileByte.length);//生成本地圖片檔案
        imageOutput.close();
            
        PdfWriter.getInstance(document, new FileOutputStream(filePath));  //itextpdf檔案
//        document.setPageSize(PageSize.A2);
        document.open();
        document.add(new Paragraph("JUST TEST ..."));
        Image image = Image.getInstance(imagePath);  //itext-pdf-image
        float heigth = image.getHeight();
                float width = image.getWidth();
                int percent = getPercent2(heigth, width);    //按比例縮小圖片
                image.setAlignment(Image.MIDDLE);
                image.scalePercent(percent+3);
        document.add(image);
        document.close();
    
        result.setSuccess(true);
        operatelogService.addOperateLogInfo(request, "匯出成功:成功匯出簡報Pdf");
    }catch (DocumentException de) {
        System.err.println(de.getMessage());
    }
    catch (Exception e) {
        e.printStackTrace();
        result.setSuccess(false);
        result.setErrorMessage(e.toString());
        try {
            operatelogService.addOperateLogError(request, "匯出失敗:伺服器異常");
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
    response.getWriter().print(JSONObject.fromObject(result).toString());
}

private static int getPercent2(float h, float w) {
    int p = 0;
    float p2 = 0.0f;
    p2 = 530 / w * 100;
    p = Math.round(p2);
    return p;
}

iText是著名的開放原始碼的站點sourceforge一個專案,是用於生成PDF文件的一個java類庫。

處理速度快,支援很多PDF"高階"特性。

但是itext出錯的時候不會報錯,直接跳過去,回頭看pdf文件損壞,找不到出錯原因,真是急死人。

最後感謝網路上有關的博文和貼子以及百度搜索。

轉自:http://my.oschina.net/u/2462382/blog/516016?p={{currentPage%201}}

其他圖片傳後臺參考資料:http://www.cnblogs.com/skyHF/p/5145334.html
                                      http://my.oschina.net/u/565351/blog/692777
                                      http://www.cnblogs.com/skyHF/p/5145334.html