无法从来自 HTML 的 jsPDF 进行 AJAX 调用

unable to make AJAX call from jsPDF fromHTML

我有一个简单的结构,可以从 jsPDF 生成 PDF,获取 'datauristring' 并将其传递到 AJAX 请求中。但是,AJAX 方法不会触发。当它尝试 'send' 时,它会抛出异常 'h is undefined'。我通过跟踪 XHR 请求发现了这一点,它出现在 jQuery 库中。我能不能在 jsPDF 回调后这么快就触发 AJAX 请求?

我应该注意到我正在将 PDF 发送到一个服务,该服务正在将该 pdf 与另一个 pdf 合并并返回一个全新的文档。

var docX = new jsPDF("p", "pt", "letter");
margins = {
    top: 20,
    bottom: 20,
    left: 20,
    width: 522
};
specialElementHandlers = {
  // element with id of "bypass" - jQuery style selector
  '#bypassme': function (element, renderer) {
      // true = "handled elsewhere, bypass text extraction"
      return true
  }
};
docX.fromHTML (
    document.getElementById('productModalContent'),
    margins.left,
    margins.top, {
        'width' : margins.width,
        'elementHandlers': specialElementHandlers
    },
    function (dispose) {
        specDoc = (docX.output('datauristring'));
        console.log(dispose);
        //docX.save('asdfas.pdf');
        //console.log(specDoc);
        processPDF(specDoc);
    }, margins
);  
function processPDF(doc) {
  console.log(doc.length);

  $.ajax({
      type: "POST",
      url: "https://someurl",
      data: {
          'partNumber' : '$!{rawPartNumber}',
          'region' : '$!{regionContentlet.code}',
          'doc' : doc
      },
      cache: false,
      success: function(data) {
          console.log("success?");
          var link=document.createElement('a');
          link.href='data:application/pdf;base64,' + data;
          link.download="myfile.pdf";
          link.setAttribute('target', '_blank');
          link.click();
      },
      error: function(data) {
          console.log(data); 
      }
  });

}

编辑:删除 ajax 并添加提取。

const response = await fetch('myurl', {
        method: 'POST',
        body: {
            'partNumber' : '$!{rawPartNumber}',
            'region' : '$!{regionContentlet.code}',
            'myDiv' : doc
        }
    });

对于任何可能因这个问题而停下来的人,我确实解决了我的问题。我无法从 jsPDF 的 fromHTML 函数中调用 AJAX 来工作。我最终将第一个 PDF 作为 base64 字符串,然后调用 jsPDF 的 fromHTML 获取第二个 PDF 数据集,最后使用 pdf-lib 在 js 中将两个 PDF 拼接在一起。

<script src="https://unpkg.com/jspdf@latest/dist/jspdf.min.js"></script>
<script src="https://unpkg.com/pdf-lib/dist/pdf-lib.js"></script>
<script src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
<script>

async function processPDF() {

    $.ajax({
        type: "POST",
        url: 'mypdfurl',
        data: {

        },
        cache: false,
        success: function(data) {
            console.log("success?");
            var docX = new jsPDF("p", "pt", "letter");
                margins = {
                top: 20,
                bottom: 20,
                left: 20,
                width: 575,             
                };
                specialElementHandlers = {
                    // element with id of "bypass" - jQuery style selector
                    '#bypassme': function (element, renderer) {
                        // true = "handled elsewhere, bypass text extraction"
                        return true
                    },
                    '.info': function (element, renderer) {
                        element.style.fontSize = "12px";
                    },
                    '.spec': function (element, renderer) {
                        element.style.fontSize = "12px";
                    },
                    '.attribute': function (element, renderer) {
                        element.style.fontSize = "12px";
                    },
                    '#logoProductPrint': function(element, renderer) {
                        var ele = element.firstElementChild;
                        ele.setAttribute("style", "width:80px;height:50px");                            
                    },

                };
            var itm = document.getElementById('productPrint');
            var itm_p = itm.cloneNode(true);
            synchronizeCssStyles(itm, itm_p, true);

            docX.fromHTML (
                //document.getElementById('productPrint'),
                itm_p,
                margins.left,
                margins.top, 
                {
                    'width' : margins.width,
                    'elementHandlers': specialElementHandlers,
                },
                async function (dispose) {
                    var specDoc = (docX.output('datauristring'));

                    const pdfDoc = await PDFLib.PDFDocument.create();
                    var d = 'data:application/pdf;base64,' + data;
                    const firstDoc = await PDFLib.PDFDocument.load(d);
                    const secondDoc = await PDFLib.PDFDocument.load(specDoc);

                    const firstPage = await pdfDoc.copyPages(firstDoc, [0]);
                    pdfDoc.addPage(firstPage[0]);
                    const secondPage = await pdfDoc.copyPages(secondDoc, [0]);

                    pdfDoc.addPage(secondPage[0]);
                    const pdfBytes = await pdfDoc.save();


                    const blob = new Blob([pdfBytes], { type: 'application/pdf' });
                    const blobUrl = URL.createObjectURL(blob);

                    var link=document.createElement('a');
                    link.href=blobUrl;

                    link.setAttribute('target', '_blank');
                    link.click();

                }, margins
            );     


        },
        error: function(data) {
            console.log(data); 
        }
    });

    function synchronizeCssStyles(src, destination, recursively) {

    // if recursively = true, then we assume the src dom structure and destination dom structure are identical (ie: cloneNode was used)

    // window.getComputedStyle vs document.defaultView.getComputedStyle 
    // @TBD: also check for compatibility on IE/Edge 
    destination.style.cssText = document.defaultView.getComputedStyle(src, "").cssText;

    if (recursively) {
        var vSrcElements = src.getElementsByTagName("*");
        var vDstElements = destination.getElementsByTagName("*");

        for (var i = vSrcElements.length; i--;) {
            var vSrcElement = vSrcElements[i];
            var vDstElement = vDstElements[i];
//          console.log(i + " >> " + vSrcElement + " :: " + vDstElement);
            vDstElement.style.cssText = document.defaultView.getComputedStyle(vSrcElement, "").cssText;
        }
      }
    }
}

您不能使用第一种方法的原因是 b/c 您必须将其作为 blob 获取,这样 jQuery 和 xhr 都不会尝试将二进制数据编码为文本。这样你就会得到损坏的数据。 您需要将其作为原始数据获取。 jQuery 不擅长这个 b/c 你不能把 responsetype 变成一个 blob。所以你需要自己写xhr请求或者使用fetch api fetch(url).then(r => r.blob()).then(code)

但是如果我在你那里,我应该从 base64 恢复到原始二进制文件以保存数据并使用(可能隐藏的)<from method="https://someurl" hidden> 使用正确的响应下载 pdf headers