DataTables图像(或至少图像标题)导出为PDF

时间:2016-01-29 17:42:54

标签: pdf datatables-1.10

使用DataTables和Buttons( NOT TableTools,已退役)扩展名。有些单元格有进度条和小图标。有没有办法将这些图像(或至少它们的标题)导出为PDF?在此页面上发现了一些可能的黑客攻击,但所有这些都是针对已退役的TableTools。

已检查https://datatables.net/reference/button/pdfhttps://datatables.net/reference/api/buttons.exportData%28%29,但找不到任何方法来实现此目标。通过添加此代码进行测试:

stripHtml: false

但整个HTML代码(如img src = ...)包含在PDF文件中而不是图像中。

如果无法导出图像,是否有办法导出每个图像的至少alt或title属性?那就足够了。

4 个答案:

答案 0 :(得分:11)

我假设您使用的是pdfHtml5。 dataTables使用pdfmake来导出pdf文件。当在浏览器中使用pdfmake时,它需要将图像定义为base64编码的dataurls。

示例:您在某些行的第一列中呈现了<img src="myglyph.png"> - 这些字形应包含在PDF中。首先创建一个Image对字形的引用:

var myGlyph = new Image();
myGlyph.src = 'myglyph.png';

在您的customize功能中,您现在必须

1)使用应包含在PDF中的所有图像构建字典 2)用text个节点替换image个节点以引用图像

buttons : [
    { 
    extend : 'pdfHtml5',
    customize: function(doc) {

        //ensure doc.images exists
        doc.images = doc.images || {};

        //build dictionary
        doc.images['myGlyph'] = getBase64Image(myGlyph);
        //..add more images[xyz]=anotherDataUrl here

        //when the content is <img src="myglyph.png">
        //remove the text node and insert an image node
        for (var i=1;i<doc.content[1].table.body.length;i++) {
            if (doc.content[1].table.body[i][0].text == '<img src="myglyph.png">') {
                delete doc.content[1].table.body[i][0].text;
                doc.content[1].table.body[i][0].image = 'myGlyph';
            }
        }
    },
    exportOptions : {
        stripHtml: false
    }
}

以下是getBase64Image函数

的示例
function getBase64Image(img) {
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);
    return canvas.toDataURL("image/png");
}

如果您只想在PDF中显示title图像 - 或者以任何其他方式想要操纵PDF的文本内容 - 那么它会更容易一些。每行中每列的内容可以通过exportOptions.format.body回调格式化

buttons : [
    { 
    extend : 'pdfHtml5',
    exportOptions : {
        stripHtml: false
        format: {
            body: function(data, col, row) {
                var isImg = ~data.toLowerCase().indexOf('img') ? $(data).is('img') : false;
                if (isImg) {
                    return $(data).attr('title');
                }
                return data;
            }
        }
    }
]

format.body无法与图像一起使用的原因是,只允许我们将数据传递回PDF文档的text节点部分。

另见

答案 1 :(得分:6)

由于没有收到任何建议,我不得不进行黑客攻击,以便按照我想要的方式格式化PDF文件。

如果某人有同样的问题,您可以使用隐藏的跨度在图像本身附近显示图像alt / title。我敢肯定这不是最好的做法,但它会做到这一点。所以代码看起来像:

<img src='image.png' alt='some_title'/><span class='hidden'>some_title</span>

这样,数据表只显示图像,而PDF文件将包含您需要的文本。

答案 2 :(得分:1)

这是我的密码!

HTML

<div class="dt-btn"></div>
<table>
  <thead><tr><th>No</th><th>IMAGE</th><th>NOTE</th></tr></thead>
  <tbody>
    <tr>
      <td>{{$NO}}</td>
      <td>{{$imgSRC}}</td>
      <td>{{$NAME}}<br />
          {{$GRADE}}<br />
          {{$PROFILE}}<br />
          {{$CODE}}<br />
      </td>
    </tr>
  </tbody>
</table>

JAVASCRIPT

$.extend( true, $.fn.dataTable.defaults, {
buttons: [{
  text: '<i class="bx bx-download font-medium-1"></i><span class="align-middle ml-25">Download PDF</span>',
  className: 'btn btn-light-secondary mb-1 mx-1 dnPDF',
  extend: 'pdfHtml5',
  pageSize: 'A4',
  styles: {
   fullWidth: { fontSize: 11, bold: true, alignment: 'left', margin: [0,0,0,0] }
  },
  action: function ( e, dt, node, config ) {
    var that = this;
    setTimeout( function () {
      $.fn.dataTable.ext.buttons.pdfHtml5.action.call(that, e, dt, node, config);
      $( ".donePDF" ).remove();
      $( ".dnPDF" ).prop("disabled", false);
    }, 50);
  },
  customize: function(doc) {
    doc.defaultStyle.fontSize = 11;
    doc.defaultStyle.alignment = 'left';
    doc.content[1].table.dontBreakRows = true;
    if (doc) {
      for (var i = 1; i < doc.content[1].table.body.length; i++) {
        // 1st Column - display IMAGE
        var imgtext = doc.content[1].table.body[i][0].text;
        delete doc.content[1].table.body[i][0].text;
        jQuery.ajax({
          type: "GET",
          dataType: "json",
          url: "{{route('base64')}}",
          data: { src: imgtext },
          async: false,
          success: function(resp) {
            //console.log(resp.data);
            doc.content[1].table.body[i][0] = {
                margin: [0, 0, 0, 3],
                alignment: 'center',
                image: resp.data,
                width: 80,
                height: 136
            };
          }
        });
        // 2nd Column - display NOTE(4 line)
        var bodyhtml = doc.content[1].table.body[i][1].text;
        var bodytext = bodyhtml.split("\n");
        var bodystyle = []
        for (var j = 0; j < bodytext.length; j++) {
          switch(j) {
            case 0:
              // NAME
              var _text = { margin:[0, 0, 0, 3], color:"#000000", fillColor:'#ffffff', bold:true, fontSize:13, alignment:'center', text:bodytext[j] };
              break;
            case 1:
              // GRADE
              var _text = { margin:[0, 0, 0, 3], color:"blue", fillColor:'#ffffff', bold:false, fontSize:11, alignment:'left', text:bodytext[j] };
              break;
            case 3:
              // CODE
              var _text = { margin:[0, 0, 0, 3], color:"#000000", fillColor:'#ffffff', bold:true, fontSize:11, alignment:'left', text:bodytext[j] };
              break;
            default:
              // OTHERS
              var _text = { margin:[0, 0, 0, 3], color:"#000000", fillColor:'#ffffff', bold:false, fontSize:11, alignment:'left', text:bodytext[j] };
              break;
          }
          bodystyle[j] = _text;
        };
        doc.content[1].table.body[i][1] = bodystyle;
      }
    }
  },
  exportOptions: {
    columns: [ 1, 2 ],
    stripNewlines: false,
    stripHtml: true,
    modifier: {
      page: 'all' // 'all', 'current'
    },
  }
}],
columns: [
  { className: 'iNo', orderable: true, visible: true},
  { className: 'iIMG', orderable: false, visible: false },
  { className: 'iPDF', orderable: false, visible: false, responsivePriority: 10001 } ]
});
var table = $('#table').DataTable();
table.buttons().container().appendTo('.dt-btn');
$('.dnPDF').on('click', function(){
  $(this).append('<span class="spinner-border spinner-border-sm donePDF" role="status" aria-hidden="true"></span>').closest('button').attr('disabled','disabled');
});
$.fn.dataTable.Buttons.defaults.dom.container.className = '';
$.fn.dataTable.Buttons.defaults.dom.button.className = 'btn';

PHP

public function base64(Request $request)
{
  $request->validate([
    'src' => 'required|string'
  ]);
  $fTYPE = pathinfo($request->src, PATHINFO_EXTENSION);
  $fDATA = @file_get_contents($request->src);
  $imgDATA = base64_encode($fDATA);
  $imgSRC = 'data:image/' . $fTYPE . ';base64,'.$imgDATA;
  $error = ($imgDATA!='') ? 0 : 1;
  $msg = ($error) ? 'Error' : 'Success';
  return response()->json([ 'msg' => $msg, 'error'=> $error, 'data' => $imgSRC]);
}

[样本] [1]:https://i.stack.imgur.com/35Wlm.jpg

答案 3 :(得分:0)

davidkonrad's answer之外。我动态创建了所有base64图像,并在Datatables pdfmake中使用它们,如下所示:

for (var i = 1; i < doc.content[2].table.body.length; i++) {
    if (doc.content[2].table.body[i][1].text.indexOf('<img src=') !== -1) {
        html = doc.content[2].table.body[i][1].text;

        var regex = /<img.*?src=['"](.*?)['"]/;
        var src = regex.exec(html)[1];


        var tempImage = new Image();
        tempImage.src = src;

        doc.images[src] = getBase64Image(tempImage)

        delete doc.content[2].table.body[i][1].text;
        doc.content[2].table.body[i][1].image = src;
        doc.content[2].table.body[i][1].fit = [50, 50];
    }

    //here i am removing the html links so that i can use stripHtml: true,
    if (doc.content[2].table.body[i][2].text.indexOf('<a href="details.php?') !== -1) {
        html = $.parseHTML(doc.content[2].table.body[i][2].text);
        delete doc.content[2].table.body[i][1].text;
        doc.content[2].table.body[i][2].text = html[0].innerHTML;
    }

}