我正在用jsPDF在web应用程序中创建PDF文档,将该文档发送给Perl,并让Perl通过电子邮件发送它,它工作得很好。然而,当我向PDF文档中添加图像时,它就失效了,因为Adobe Reader说该文件已损坏。这个应用程序是巨大的,所以这里有一个类似的相关代码的存根,以相同的方式工作:
html:<!DOCTYPE html>
<html>
<head>
<script src="https://<myserver>/js/jquery.js"></script>
<script src="https://<myserver>/js/jspdf.js"></script>
<script src="https://<myserver>/js/jspdf.plugin.addimage.js"></script>
<script src="https://<myserver>/test/pdf.js"></script>
</head>
<body>
<input type="submit" id="go">
</body>
</html>
js:
$(document).ready(function() {
$('#go').on('click',function() {
//create PDF
var imgData = 'data:image/jpeg;base64,<dataurlencoded image string>';
var doc = new jsPDF('p','pt','a4');
doc.addImage(imgData, 'JPEG', 22, 22, 138, 28);
doc.text(30, 120, 'Lorem Ipsum!');
var perl_pdf = doc.output();
//send PDF to perl and have perl email it
$.ajax({
type: "POST",
url: "https://<myserver>/cgi-bin/pdf.pl",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
dataType: "json",
data: "perl_pdf="+encodeURIComponent(perl_pdf),
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("error: "+ XMLHttpRequest.responseText + ", textStatus: " + textStatus + ", errorThrown: " + errorThrown);
},
success: function(data){
alert("Success: "+data.success);
}
});
});
});
perl: #!d:/perl/bin/perl.exe -w
use strict;
use warnings;
use CGI qw(:all);
use MIME::Lite;
use MIME::Base64;
my $q = CGI->new();
my $pdf_doc = $q->param('perl_pdf');
open (OUTFILE, '>pdf.pdf') or die "Could not open file";
binmode(OUTFILE);
print OUTFILE decode_base64($pdf_doc);
close OUTFILE;
my $from_address = '<from_address>';
my $to_address = '<to_address>';
my $mail_host = '<smtp_server>';
my $subject = 'PDF Test';
my $message_body = "The PDF is attached...nn";
my $my_file = 'pdf.pdf';
my $out_file = 'test.pdf';
my $msg = MIME::Lite->new (
From => $from_address,
To => $to_address,
Subject => $subject,
Type => 'multipart/mixed') or die "Cannot create multipart container: $!n";
$msg->attach (
Type => 'TEXT',
Data => $message_body) or die "Cannot attach text: $!n";
$msg->attach (
Type => 'application/pdf',
Path => $my_file,
Filename => $out_file,
Disposition => 'attachment') or die "Cannot attach file: $!n";
MIME::Lite->send('smtp', $mail_host, Timeout=>60);
$msg->send;
my $json = qq{{"success" : "This worked"}};
print $q->header(-type => "application/json", -charset => "utf-8");
print $json;
如果我将Ajax调用和输出创建替换为…
doc.output('dataurlnewwindow',{});
…然后它正确地显示在一个新的浏览器选项卡中,所以我知道图像被正确插入。从我在搜索中发现的,似乎是一些编码问题,但我还没有找到解决问题的方法。我怎样才能把带有图像的PDF文档成功地发送到服务器上的Perl,使其不损坏?
最新版本的JSPDF已解决此问题。如果您使用xmlhttprequest.send
或ajax调用的一部分发送PDF与图像到服务器作为表单数据。
请用jsPDF.output('blob')
代替jsPDF.output()
。
这将不会破坏pdf发送到服务器。
好吧,这可能不会帮助你,因为你使用的是Windows,只是演示:
我的测试perl脚本称为app.pl
:
#!/usr/bin/env perl
use strict;
use warnings;
use CGI qw(:all);
my $q = CGI->new();
my $pdf_doc = $q->param('perl_pdf');
open (my $fp, '>', 'pdf.pdf') or die "Could not open file";
print $fp $pdf_doc;
close $fp;
print "OKn";
创建一个名为x.pdf
的pdf文件。
$ ls -l x.pdf
-rw-r--r--@ 1 jm staff 100838 18 mar 19:20 x.pdf
在端口3000上运行一个简单的测试web服务器
plackup --port 3000 -MPlack::App::WrapCGI -e 'Plack::App::WrapCGI->new( script => "./app.pl", execute => 1)->to_app'
说:
HTTP::Server::PSGI: Accepting connections at http://0:3000/
从另一个终端通过curl
命令发送base64编码的文件
$ curl -i -F perl_pdf="$(base64 < x.pdf)" 0:3000/
反应:
HTTP/1.0 200 OK
Date: Tue, 18 Mar 2014 20:15:40 GMT
Server: HTTP::Server::PSGI
Content-Length: 3
OK
服务器说:
127.0.0.1 - - [18/Mar/2014:21:06:00 +0100] "POST / HTTP/1.1" 200 3 "-" "curl/7.35.0"
并保存文件pdf.pdf
该文件具有base64编码的内容。
$ ls -la pdf.pdf
-rw-r--r-- 1 jm staff 134452 18 mar 21:06 pdf.pdf
解码它
$ base64 -D < pdf.pdf >decoded.pdf
与原
比较$ cmp decoded.pdf x.pdf
$ ls -la decoded.pdf
-rw-r--r-- 1 jm staff 100838 18 mar 21:18 decoded.pdf
no difference -发送PDF -成功。
很遗憾,我帮不了你更多的忙,因为:
- 您正在使用Windows
- 和我不懂Javascript…
考虑检查:
- 如何在JavaScript中编码一个字符串到Base64 ?
- 我如何使用Javascript和XMLHttpRequest加载二进制图像数据?
我找到问题了。在将图像添加到PDF之前,将文件发送到Perl时不需要编码,这显然是因为在发送字符串时没有丢失(或没有丢失相关的)二进制信息。当然,添加图像将非常相关的二进制信息添加到字符串中,而这些信息不能在urlencoded消息中发送。编码/解码应该照顾到这一点,但是…
我尝试了许多不同的Base64编码/解码方法,但我的文件仍然最终损坏。我最后偶然发现了一个类似的问题,有人提到将字符串作为URL的一部分发送会将+符号转换为空格。我删除了Perl端的解码,以查看编码后的字符串是什么样子,整个字符串中确实有几个空格。用
转换回来$pdf_doc =~ s/ /+/g;
在让Perl写入文件之前修复了这个问题。该文件现在可以在服务器端的Adobe中拉出。