我在我的网站上使用Coldfusion 10和CFWheels。 基本上我的网站有很多不同类型的表单,有自己的控制器和视图。对于每个表单,用户可以选择动态生成表单的PDF并下载。它基本上加载了控制器数据,但是当它使用参数“pdf”命中视图时,它会执行以下操作,生成PDF并在浏览器中打开文档:
<cfdocument format="PDF" saveAsName="#formtype#_#id#.pdf">
#includePartial("/printView")#
</cfdocument>
这些PDF中的每一个都可以有多个页面,具体取决于添加的订单项数量。就像我在开始时所说的那样,有多种类型的表单,因此它们将拥有自己的控制器和视图以及带有打印视图的PDF生成。这些表单都是自定义的,并与像像cargoID这样的ID相关联。所以我可以有一个包含2种A型和1种B型和3种C型等的货物。我需要做的是生成1份PDF,所有表格根据货物合并在一起。因此,以我的例子为例,货件的合并PDF将包含A型的2种形式,B型的1种形式,以及C型的3种全部合并。
目前我正在做的是对每个动态生成的PDF页面进行http“GET”调用,将其保存到临时目录,然后在最后合并它们。
我加载货件,对于每种不同类型的表单,我执行以下操作,其中urlPath是生成动态PDF的视图的路径:
var httpService = new http();
httpService.setMethod("GET");
httpService.setUrl(urlPath);
invoice = httpService.send().getPrefix().filecontent.toByteArray();
var fullPath = "#filePath##arguments.type#_#id#.pdf";
//write files in temp directory
FileWrite(fullPath, invoice);
获取PDF并将其写入文件后,我将路径保存在数组中以供参考,这样我就可以循环并合并数组中所有引用的文件,然后删除保存文件的临时目录。
我之所以这样做,是因为控制器和视图已经设置好,并且可以动态生成各个PDF。 如果我尝试加载(所有关联的表单)并将所有内容放在一个文件中,我将不得不添加所有相同的控制器逻辑来加载每个表单特定的东西和相关的视图,但这些已经存在于单个页面视图中。
有更好的方法吗? 如果只有少量PDF,但如果出货中有很多不同的表格,如20,那么它工作正常,那么它非常慢,因为我们没有CF Enterprise,我相信cfdocument是单线程的。表格必须动态生成,以便包含最新数据。
Chris的更新
我添加了一些代码来显示各种表单的外观。我验证并加载了一些其他的东西,但我把它剥离了以获得一般的想法:
控制器/ Invoices.cfc
路径可能类似于:/ shipment / [shipmentkey] /发票/ [key]
public void function show(){
// load shipment to display header details on form
shipment = model("Shipment").findOne(where="id = #params.shipmentkey#");
// load invoice details to display on form
invoice = model("Invoice").findOne(where="id = #params.key#");
// load associated invoice line items to display on form
invoiceLines = model("InvoiceLine").findAll(where="invoiceId = #params.key#");
// load associated containers to display on form
containers = model("Container").findAll(where="invoiceid = #params.key#");
// load associated snumbers to display on form
scnumbers = model("Scnumber").findAll(where="invoiceid = #params.key#");
}
控制器/ Permits.cfc
路径可能类似于:/ shipment / [shipmentkey] / permits / [key]
public void function show(){
// load shipment to display header details on form
shipment = model("Shipment").findOne(where="id = #params.shipmentkey#");
// load permit details to display on form
permit = model("Permit").findOne(where="id = #params.key#");
// load associated permit line items to display on form
permitLines = model("PermitLine").findAll(where="permitId = #params.key#");
}
控制器/ Nafta.cfc
路径可能类似于:/ shipment / [shipmentkey] / naftas / [key]
public void function show(){
// load shipment to display header details on form
shipment = model("Shipment").findOne(where="id = #params.shipmentkey#");
// load NAFTA details to display on form
nafta = model("NAFTA").findOne(where="id = #params.key#");
// load associated NAFTA line items to display on form
naftaLines = model("NaftaLine").findAll(where="naftaId = #params.key#");
}
目前我的视图基于名为“view”的URL参数,其中值可以是“print”或“pdf”。
print - 显示打印视图,该视图几乎是没有网页页眉/页脚等的表单的精简版本。
pdf - 调用我在问题顶部粘贴的cfdocument代码,该代码使用printView生成PDF。
我认为我不需要发布“show.cfm”代码,因为它只是一堆div和表格,显示每个特定表单的具体信息。
请注意,这些只是3个示例表单类型,并且有10种类型可能与1个货件相关联,而PDF需要合并。每种类型也可在装运中重复多次。例如,货件可能包含10张不同的发票,其中包含5张许可证和3张NAFTA。
为了使事情稍微复杂一点,货物可以有两种类型:US Bound或Canada Bound,并且基于这种不同的表格类型可以与货物相关联。因此,加拿大的发票将与美国的发票完全不同,因此模型/表格不同。
目前要进行合并我有一个控制器,它执行类似下面的操作(注意我剥离了很多验证,加载其他对象以简化)
public any function displayAllShipmentPdf(shipmentId){
// variable to hold the list of full paths of individual form PDFs
formList = "";
shipment = model("shipment").findOne(where="id = #arguments.shipmentId#");
// path to temporarily store individual form PDFs for later merging
filePath = "#getTempDirectory()##shipment.clientId#/";
if(shipment.bound eq 'CA'){
// load all invoices associated to shipment
invoices = model("Invoice").findAll(where="shipmentId = #shipment.id#");
// go through all associated invoices
for(invoice in invoices){
httpService = new http();
httpService.setMethod("get");
// the following URL loads the invoice details in the Invoice controller and since I'm passing in "view=pdf" the view will display the PDF inline in the browser.
httpService.setUrl("http://mysite/shipments/#shipment.id#/invoices/#invoice.id#?view=pdf");
invoicePdf = httpService.send().getPrefix().fileContent.toByteArray();
fullPath = "#filePath#invoice_#invoice.id#.pdf";
// write the file so we can merge later
FileWrite(fullPath, invoicePdf);
// append the fullPath to the formList as reference for later merging
formList = ListAppend(formList, fullPath);
}
// the above code would be similarly repeated for every other form type (ex. Permits, NAFTA, etc.). So it would call the path with the "view=pdf" which will load the specific form Controller and display the PDF inline which we capture and create a temporary PDF file and add the path to the formList for later merging. You can see how this can be a long process as you have several types of forms associated to a shipment and there can be numerous forms of each type in the shipment and I don't want to have to repeat each form Controller data loading logic.
}else if(shipment.bound eq 'US'){
// does similar stuff to the CA except with different forms
}
// merge the PDFs in the formList
pdfService = new pdf();
// formList contains all the paths to the different form PDFs to be merged
pdfService.setSource(formList);
pdfService.merge(destination="#filePath#shipment_#shipment.id#.pdf");
// read the merged PDF
readPdfService = new pdf();
mergedPdf = readPdfService.read(source="#filePath#shipment_#shipment.id#.pdf");
// delete the temporarily created PDF files and directory
DirectoryDelete(filePath, "true");
// convert to binary to display inline in browser
shipmentPdf = toBinary(mergedPdf);
// set the response to display the merged PDF
response = getPageContext().getFusionContext().getResponse();
response.setContentType('application/pdf');
response.setHeader("Content-Disposition","filename=shipment_#shipment.id#_#dateFormat(now(),'yyyymmdd')#T#timeFormat(now(),'hhmmss')#.pdf");
response.getOutputStream().writeThrough(shipmentPdf);
}
答案 0 :(得分:0)
请参阅:https://forums.adobe.com/thread/1121909 ...&#34; ...标准版Adobe将PDF函数限制为单个线程,...开发人员像Enterprise&#34;因此,您的开发环境将扼杀pdf,但您的CF Standard生产服务器将会窒息。
此外,您似乎没有遇到一两个pdf的问题。我有CF企业版,它正在生成pdf就好 - 几秒钟 - 然后无处不在,pdfs开始需要4分钟。上面引用的adobe帖子中的另一个评论建议检查CF正在联系自己的/ etc / hosts(?????)。好一些挖掘,我发现Windows \ system32 \ drivers \ etc \ hosts在用户发现pdfs超时前一天更新了。 IP已更改为其他一些Intranet IP,服务器名称是DNS服务器名称。我将值更改回127.0.0.1 localhost
并且瞧,pdfs在正常时间内开始渲染。