Liferay 7 CE自定义文件上传表单字段开发求助:存文档媒体+邮件发送
Hey Marco, let's work through this custom file upload form field for your "Join Us" form in Liferay 7 CE. I’ve implemented similar functionality before, so here’s a structured approach to get past your roadblocks:
First, make sure your Gradle-based form field module has the key components required for a file upload field:
- Custom Field Type Class: Extend
BaseDDMFieldTypeorBaseDDMFieldto define the field’s core behavior—this is where you’ll hook in file processing logic. - Field Renderer: Create a JSP or Freemarker renderer to render the file upload input in the form. You can use a standard HTML file input, or integrate Liferay’s built-in Documents and Media picker if you want users to select existing files too.
- Module Dependencies: Update your
build.gradleto include critical dependencies:portal-kernel,document-library-api,dynamic-data-mapping-api, andmail-api—these are non-negotiable for file handling and email attachments.
The core challenge here is capturing the uploaded file and persisting it to the DL repository. Here’s how to implement it:
- In your custom field’s processing logic (like the
setValuemethod or a form submission hook), retrieve the uploaded file from theHttpServletRequestusingrequest.getPart("your-field-name"). - Use Liferay’s
DLAppServiceto create a file entry in your target Documents and Media folder. First, create a dedicated folder for form submissions (or use your site’s default folder), then pass the file details to the service.
Example code snippet:
// Inject DLAppService via @Reference @Reference private DLAppService dlAppService; public void saveUploadedFile(HttpServletRequest request, long groupId, long targetFolderId) throws Exception { Part filePart = request.getPart("join-us-file-upload"); String fileName = filePart.getSubmittedFileName(); String mimeType = filePart.getContentType(); long fileSize = filePart.getSize(); InputStream inputStream = filePart.getInputStream(); ServiceContext serviceContext = ServiceContextFactory.getInstance(request); serviceContext.setScopeGroupId(groupId); // Create file entry in Documents and Media FileEntry fileEntry = dlAppService.addFileEntry( 0, // Use current user's ID or form submitter's ID groupId, targetFolderId, fileName, mimeType, fileName, // File title "Uploaded via Join Us form", // Description "", // Change log fileSize, inputStream, serviceContext ); // Store the file entry ID in the form field value for later email use setValue(String.valueOf(fileEntry.getFileEntryId())); }
Once the file is saved, you need to include it in the form’s notification email. Here’s a reliable approach using a form submission listener:
- Create a
DDMFormSubmitListenercomponent that triggers right after the form is submitted. - In the listener, retrieve the stored file entry ID from the form field, fetch the file content via
DLAppService, then use Liferay’sMailServiceto send an email with the attachment.
Example listener code snippet:
@Component( immediate = true, property = { "javax.portlet.name=com_liferay_dynamic_data_mapping_form_web_portlet_DDMFormPortlet", "service.ranking:Integer=100" }, service = DDMFormSubmitListener.class ) public class JoinUsFormSubmitListener implements DDMFormSubmitListener { @Reference private DLAppService dlAppService; @Reference private MailService mailService; @Override public void onDDMFormSubmit(DDMFormSubmitEvent event) throws Exception { // Get file entry ID from the custom field String fileEntryIdStr = (String) event.getDDMFormValues() .getDDMFieldValues("join-us-file-upload") .get(0) .getValue() .getString(); long fileEntryId = Long.parseLong(fileEntryIdStr); FileEntry fileEntry = dlAppService.getFileEntry(fileEntryId); // Prepare email attachment byte[] fileContent = dlAppService.getFileContent(fileEntry.getFileEntryId()); MailAttachment attachment = new MailAttachment(); attachment.setFileName(fileEntry.getFileName()); attachment.setInputStream(new ByteArrayInputStream(fileContent)); attachment.setContentType(fileEntry.getMimeType()); // Build email with form data and attachment String userName = event.getDDMFormValues() .getDDMFieldValues("name") .get(0) .getValue() .getString(); String userMessage = event.getDDMFormValues() .getDDMFieldValues("message") .get(0) .getValue() .getString(); MailMessage mailMessage = new MailMessage(); mailMessage.setFrom(new InternetAddress("noreply@yourdomain.com")); mailMessage.setTo(new InternetAddress("recruitment@yourdomain.com")); mailMessage.setSubject("New Join Us Form Submission from " + userName); mailMessage.setBody("Name: " + userName + "\n\nMessage:\n" + userMessage); mailMessage.addAttachment(attachment); mailService.sendEmail(mailMessage); } }
- Permissions: Ensure the form submitter has permission to add file entries to your target Documents and Media folder. Test with an admin first, then adjust permissions for regular users.
- File Size Limits: Check Liferay’s portal properties (
dl.file.entry.max.size,portal.upload.max.size) to make sure they’re set high enough for your use case. - Validation: Add server-side validation to restrict allowed file types (check the MIME type in your field’s validator class).
- Deployment: Verify your module is activated in Gogo Shell with
lb | grep your-module-name—common issues here include missing dependencies or incorrect component annotations.
If you hit specific snags with any of these steps, feel free to share more details and I’ll help you work through them!
内容的提问来源于stack exchange,提问作者Marco

