[英]Render a PDF file and save to object using grails Rendering and Attachmentable plugins
我試圖生成一個包含對象信息的PDF文件,然后將其附加到存儲在數據庫中的另一個對象。 我正在使用的可附件插件現在可以用於用戶端附件,但是我需要我的系統能夠自動執行此操作。
我在用:
Grails 1.3.9
可附加的0.3.0 http://grails.org/plugin/attachmentable
渲染0.4.3 http://grails.org/plugin/rendering
我已經能夠生成和顯示pdf,但不知道如何使用可附加附件來附加它。 我需要某種方式來生成生成的pdf字節數組,並將其轉換為MultipartFile,以供我調用的可附加插件功能。 我得到的錯誤表明我的參數類型無效。
我保存了object1和object2,然后生成object1的pdf,然后嘗試將其附加到object2。
預先感謝您的幫助!
Thing1控制器片段:
ByteArrayOutputStream bytes = pdfRenderingService.render(template: "/thing1/pdf", model: [thing1: thing1])
attachmentableService.addAttachment("unknown", thing2.id, bytes)
我正在嘗試調用AttachmentableService函數:
def addAttachment(def poster, def reference, CommonsMultipartFile file) {
addAttachment(CH.config, poster, reference, file)
}
def addAttachment(def config,
def poster,
def reference,
CommonsMultipartFile file) {
if (reference.ident() == null) {
throw new AttachmentableException(
"You must save the entity [${delegate}] before calling addAttachment.")
}
if (!file?.size) {
throw new EmptyFileException(file.name, file.originalFilename)
}
String delegateClassName = AttachmentableUtil.fixClassName(reference.class)
String posterClass = (poster instanceof String) ? poster : AttachmentableUtil.fixClassName(poster.class.name)
Long posterId = (poster instanceof String) ? 0L : poster.id
String filename = file.originalFilename
// link
def link = AttachmentLink.findByReferenceClassAndReferenceId(
delegateClassName, reference.ident())
if (!link) {
link = new AttachmentLink(
referenceClass: delegateClassName,
referenceId: reference.ident())
}
// attachment
Attachment attachment = new Attachment(
// file
name: FilenameUtils.getBaseName(filename),
ext: FilenameUtils.getExtension(filename),
length: 0L,
contentType: file.contentType,
// poster
posterClass: posterClass,
posterId: posterId,
// input
inputName: file.name)
link.addToAttachments attachment
if (!link.save(flush: true)) {
throw new AttachmentableException(
"Cannot create Attachment for arguments [$user, $file], they are invalid.")
}
// save file to disk
File diskFile = AttachmentableUtil.getFile(config, attachment, true)
file.transferTo(diskFile)
attachment.length = diskFile.length()
// interceptors
if(reference.respondsTo('onAddAttachment')) {
reference.onAddAttachment(attachment)
}
attachment.save(flush:true) // Force update so searchable can try to index it again.
return reference
}
Grails運行時錯誤:
groovy.lang.MissingMethodException: No signature of method: com.macrobit.grails.plugins.attachmentable.services.AttachmentableService.addAttachment() is applicable for argument types: (java.lang.String, java.lang.Long, java.io.ByteArrayOutputStream) values: [unknown, 80536, %PDF-1.4 and a long string of unreadable data...]
Possible solutions: addAttachment(java.lang.Object, java.lang.Object, org.springframework.web.multipart.commons.CommonsMultipartFile), addAttachment(java.lang.Object, java.lang.Object, java.lang.Object, org.springframework.web.multipart.commons.CommonsMultipartFile)
我添加的服務方法:
def customAddMethod(def poster, def reference, def pdfBytes) {
customAddMethod(CH.config, poster, reference, pdfBytes)
}
def customAddMethod(def config,
def poster,
def reference,
def pdfBytes) {
if (reference.ident() == null) {
throw new AttachmentableException(
"You must save the entity [${delegate}] before calling customAddMethod.")
}
String delegateClassName = AttachmentableUtil.fixClassName(reference.class)
String posterClass = (poster instanceof String) ? poster : AttachmentableUtil.fixClassName(poster.class.name)
Long posterId = (poster instanceof String) ? 0L : poster.id
String filename = "File Name"
// link
def link = AttachmentLink.findByReferenceClassAndReferenceId(
delegateClassName, reference.ident())
if (!link) {
link = new AttachmentLink(
referenceClass: delegateClassName,
referenceId: reference.ident())
}
// attachment
Attachment attachment = new Attachment(
// file
name: "File Name",
ext: "pdf",
length: 0L,
contentType: "application/pdf",
// poster
posterClass: posterClass,
posterId: posterId,
// input
inputName: "File Name")
link.addToAttachments attachment
if (!link.save(flush: true)) {
throw new AttachmentableException(
"Cannot create Attachment for arguments [$user, $file], they are invalid.")
}
// save file to disk
byte[] bytes = pdfBytes.toByteArray(); //convert ByteArrayOutputStream to ByteArray
File diskFile = AttachmentableUtil.getFile(config, attachment, true) //file path
FileOutputStream fos = new FileOutputStream(diskFile); //open file output stream to write to
fos.write(bytes); //write rendered pdf bytes to file
fos.flush();
fos.close();
attachment.length = diskFile.length()
// interceptors
if(reference.respondsTo('onAddAttachment')) {
reference.onAddAttachment(attachment)
}
attachment.save(flush:true) // Force update so searchable can try to index it again.
return reference
}
好像您引用的AttachmentableService(來自Attachmentable插件)假定它正在處理文件上載情況,因此您可以通過request.getFile()輕松獲取MultipartFile實例。 事實並非如此-您正在通過“渲染”插件創建文件,並且希望將該文件附加到域對象,對嗎?
您可以嘗試通過首先將pdf字節寫入磁盤,然后通過DiskFileItemFactory創建DiskFileItem來手動構造CommonsMultipartFile實例。 請參閱這篇文章,以了解我的想法: 如何從絕對文件路徑制作CommonsMultipartFile?
另一個更好的選擇可能是簽出該插件的源代碼,並添加不需要您進行旋轉的方法-也許是addAttachment方法的版本,該方法可以接受File或OutputStream-並將PR提交給插件作者。 (看起來他們正在為合格的域對象添加“ addAttachment”方法,這也需要一個CommonsMultipartFile)。
否則,您可能只需要創建自己的服務即可提供基本的最終結果,這顯然是創建AttachmentLink和關聯的Attachment實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.