You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

1. Foundation: Custom Form Field Module Structure

First, make sure your Gradle-based form field module has the key components required for a file upload field:

  • Custom Field Type Class: Extend BaseDDMFieldType or BaseDDMField to 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.gradle to include critical dependencies: portal-kernel, document-library-api, dynamic-data-mapping-api, and mail-api—these are non-negotiable for file handling and email attachments.
2. Saving Uploaded Files to Documents and Media

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 setValue method or a form submission hook), retrieve the uploaded file from the HttpServletRequest using request.getPart("your-field-name").
  • Use Liferay’s DLAppService to 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()));
}
3. Attaching the File to Form Submission Emails

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 DDMFormSubmitListener component 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’s MailService to 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);
    }
}
4. Key Troubleshooting Tips
  • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 07:44:10