如何在Liferay模块项目中将input type=file值存入Java变量
这个需求完全可实现,你之前几次尝试失败都是踩了Liferay文件上传的常规坑,以下是具体说明和可运行的实现方案。
核心失败原因
- 普通
request.getParameter()仅能读取字符串类型的表单参数,本身就不支持multipart/form-data编码的文件上传请求,所有Java Web场景下用这个方法都拿不到文件数据 - Liferay的
ParamUtil默认没有直接返回File类型的方法,是因为框架默认不会主动把上传文件落盘生成持久化的File对象,避免不必要的磁盘IO和临时文件泄漏问题 - 自行构造上传请求失败,基本是因为没加Liferay要求的CSRF校验参数、没设置正确的表单编码,或是没走Liferay MVC Portlet的标准请求处理流程
分步实现方案
1. JSP端编写上传表单
表单必须设置enctype="multipart/form-data",同时带上Liferay要求的基础校验参数,示例代码如下:
<%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %> <%@ taglib uri="http://liferay.com/tld/aui" prefix="aui" %> <portlet:actionURL var="uploadFileActionUrl" name="uploadFileToDL" /> <form action="<%= uploadFileActionUrl %>" method="post" enctype="multipart/form-data"> <aui:input name="<%= com.liferay.portal.kernel.util.Constants.CMD %>" type="hidden" value="addFile" /> <aui:input type="file" name="uploadFile" label="选择要上传的文件" /> <aui:button type="submit" value="上传到文档库" /> </form>
上述代码里的
name="uploadFile"要和后端取文件的参数名保持一致
2. 后端Portlet编写处理逻辑
不需要自己解析上传流,Liferay已经在请求进入Portlet前完成了解析,直接通过UploadPortletRequest对象拿文件即可,拿到文件后可直接调用DL服务存入文档库,示例代码如下:
import com.liferay.portal.kernel.upload.UploadPortletRequest; import com.liferay.portal.kernel.util.PortalUtil; import com.liferay.document.library.kernel.service.DLAppServiceUtil; import com.liferay.document.library.kernel.model.DLFolderConstants; import com.liferay.portal.kernel.repository.model.FileEntry; import javax.portlet.ActionRequest; import javax.portlet.ActionResponse; import java.io.InputStream; import java.io.File; public class CustomFileUploadPortlet extends MVCPortlet { public void uploadFileToDL(ActionRequest actionRequest, ActionResponse actionResponse) throws Exception { // 转换普通请求为上传请求对象,为核心步骤 UploadPortletRequest uploadRequest = PortalUtil.getUploadPortletRequest(actionRequest); // 如果确实需要java.io.File类型变量,直接调用此方法获取Liferay生成的临时文件 File tempUploadFile = uploadRequest.getFile("uploadFile"); // 更推荐直接拿流处理,减少磁盘IO String sourceFileName = uploadRequest.getFileName("uploadFile"); String contentType = uploadRequest.getContentType("uploadFile"); long fileSize = uploadRequest.getSize("uploadFile"); InputStream fileInputStream = uploadRequest.getFileAsStream("uploadFile"); // 写入Document Library文档库逻辑,示例为存在当前站点根目录 long scopeGroupId = PortalUtil.getScopeGroupId(actionRequest); long targetFolderId = DLFolderConstants.DEFAULT_PARENT_FOLDER_ID; // 可替换为指定文件夹ID FileEntry savedFileEntry = DLAppServiceUtil.addFileEntry( scopeGroupId, targetFolderId, sourceFileName, contentType, sourceFileName, "上传文件备注", "版本变更说明", fileInputStream, fileSize, actionRequest ); // 此处可追加上传完成后的跳转、提示等自定义业务逻辑 } }
注意:通过getFile()拿到的临时文件会在请求结束后被Liferay自动清理,需要长期存储必须转存或直接写入文档库
避坑提示
- 不要手动引入第三方文件上传库(如commons-fileupload)重复解析请求,Liferay已经提前消费过请求流,重复解析会拿不到文件数据
- 存入指定文件夹时替换
targetFolderId为目标文件夹ID即可,注意要确保当前登录用户拥有该文件夹的上传权限,否则会抛出权限校验异常 - 不要省略表单的
enctype="multipart/form-data"配置,否则浏览器不会把文件数据写入请求体,任何后端逻辑都拿不到上传文件
内容的提问来源于stack exchange,提问作者Lincolnmyth
相关产品推荐
相关产品推荐

