PDF.js如何将填写完成的Acroform表单PDF存储到服务器
问题根因说明
pdf.js默认示例查看器中,检测到当前加载的PDF包含Acroform表单时,会主动给下载按钮添加hidden属性隐藏,本质是早期版本对表单数据持久化导出的兼容性做的限制。你手动取消隐藏后能下载带填写数据的PDF,说明你使用的版本已经支持表单数据写入导出逻辑,仅前端UI做了隐藏限制。
实现方案步骤
1. 解除下载按钮的隐藏限制(可选)
如果需要保留前端UI的下载功能,可以找到viewer.js中关联Acroform检测和下载按钮显隐的判断逻辑,注释掉给下载按钮添加隐藏属性的代码即可。如果不需要保留UI下载按钮,可直接跳过此步骤,调用API直接导出PDF。
2. 前端导出带填写数据的PDF为Blob对象
无需触发下载按钮点击,直接调用pdf.js内置API即可导出携带最新表单数据的PDF文件:
// 等待PDF加载、表单填写完成后执行 async function exportFilledPdf() { // pdfViewer为pdf.js默认查看器的全局实例,二次封装版本可自行调整实例获取路径 const pdfDocument = pdfViewer.pdfDocument; // 导出包含所有填写数据的完整PDF二进制流 const savedData = await pdfDocument.saveDocument(); // 转换为Blob对象 return new Blob([savedData], { type: 'application/pdf' }); }
3. 前端发送POST请求上传到Servlet
使用FormData封装PDF Blob后发送请求即可:
async function uploadPdfToServlet(blob) { const formData = new FormData(); // 参数名、文件名可自行调整,和服务端接收参数保持一致即可 formData.append('filledPdf', blob, '填写完成的表单.pdf'); try { const response = await fetch('/你的Servlet访问路径', { method: 'POST', body: formData }); if (response.ok) { console.log('PDF上传成功'); } } catch (error) { console.error('PDF上传失败', error); } } // 调用示例 exportFilledPdf().then(blob => uploadPdfToServlet(blob));
4. 服务端Servlet接收保存
Servlet 3.0及以上版本可直接使用@MultipartConfig注解实现multipart类型请求的解析:
import javax.servlet.annotation.MultipartConfig; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import java.io.FileOutputStream; import java.io.InputStream; @MultipartConfig(maxFileSize = 1024 * 1024 * 50) // 单文件最大50M,可自行调整 public class PdfUploadServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) { try { // 和前端FormData的参数名保持一致 Part pdfPart = request.getPart("filledPdf"); InputStream pdfInputStream = pdfPart.getInputStream(); // 自定义服务端文件保存路径 FileOutputStream outputStream = new FileOutputStream("/服务端保存路径/用户上传表单.pdf"); byte[] buffer = new byte[1024]; int len; while ((len = pdfInputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, len); } outputStream.close(); pdfInputStream.close(); response.setStatus(HttpServletResponse.SC_OK); } catch (Exception e) { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); e.printStackTrace(); } } }
注意事项
- 若使用二次封装的pdf.js组件,需确认PDF实例的获取路径,部分封装版本会将实例挂载到自定义变量下
- 导出的PDF默认会保留所有Acroform字段的填写数据,无需额外做字段序列化处理
- 服务端可根据业务需求调整文件大小限制、存储路径、文件命名规则等配置
内容的提问来源于stack exchange,提问作者C. Rich
相关产品推荐
相关产品推荐

