java - 在 Java Spring 中将大型 PDF 添加到 zip 文件时出现状态 500 错误
问题描述
当用户将 XML 文件上传到网站时,他们可以单击下载捆绑 PDF 按钮(其中包含 /bundle/{bundleId}/data.zip 的 RequestMapping)以查看捆绑在包含在压缩文件。但是,我们发现当用户尝试上传一个包含非常大的通知的 XML 文件,然后单击 Download Bundle PDF 按钮时,服务器响应状态为 500,并且无法下载 zip 文件。目前我们正在使用字节数组方法并将输出写入 ZipOutputStream。对于大文件,我读过最好使用流而不是字节数组。我已经实现了以下代码,但是在尝试下载大文件时它仍然返回状态 500 错误。
@RequestMapping(value = "/bundle/{bundleId}/data.zip", method = RequestMethod.GET)
@Secured({GroupRoleNames.ROLE_PLACE_NOTICE})
public void getNoticePdf(@PathVariable String bundleId, ModelMap model, HttpServletRequest request, HttpServletResponse httpResponse) {
try {
OutputStream output = httpResponse.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(output);
ZipOutputStream zos = new ZipOutputStream(bos);
httpResponse.setHeader("X-Robots-Tag", "noindex,follow");
httpResponse.setContentType("application/zip");
httpResponse.setHeader("Content-Disposition:", "inline; filename=bundle_" + Math.random() + ".zip");
httpResponse.setHeader("Cache-control:", "private");
getBundlePdfAsZip(bundleId, zos);
} catch (Exception e) {
if (e instanceof DataNotFoundException) {
throw new DataNotFoundException(e);
} else {
logger.error(" error during print pdf for a single notice ", e);
httpResponse.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
@Override
public void getBundlePdfAsZip(String bundleId, ZipOutputStream zos) throws IOException {
Set<String> noticeIds = new HashSet<String>();
final BundleMetadataVO bundleMetadata = getBundleMetadata(bundleId);
if (CollectionUtils.isEmpty(bundleMetadata.getValidNoticeIds())) {
throw new DataNotFoundException("Required Parameters Missing or Search fetched zero Results");
}
RestTemplate restTemplate = new RestTemplate();
noticeIds = bundleMetadata.getValidNoticeIds();
for (String noticeId : noticeIds) {
String supplierId = getSupplierId(noticeId);
if (StringUtils.isNotEmpty(supplierId) && StringUtils.isNotBlank(supplierId)) {
ZipEntry ze = new ZipEntry(supplierId + "_" + noticeId + ".pdf");
zos.putNextEntry(ze);
} else {
ZipEntry ze = new ZipEntry(noticeId + "_" + ".pdf");
zos.putNextEntry(ze);
}
String uri = configurationProfileServices.quartzContextUri() + String.format(SINGLE_PDF_URI, noticeId);
final File ret = File.createTempFile("download", "tmp");
File file = restTemplate.execute(uri, HttpMethod.GET, null, clientHttpResponse -> {
StreamUtils.copy(clientHttpResponse.getBody(), new FileOutputStream(ret));
return ret;
});
HttpHeaders headers = restTemplate.headForHeaders(uri);
long contentLength = headers.getContentLength();
restTemplate.execute(
uri,
HttpMethod.GET,
clientHttpRequest -> clientHttpRequest.getHeaders().set(
"Range",
String.format("bytes=%d-%d", file.length(), contentLength)),
clientHttpResponse -> {
StreamUtils.copy(clientHttpResponse.getBody(), new FileOutputStream(file, true));
return file;
});
}
zos.closeEntry();
zos.close();
}
我是否需要将文件的内容写回 ZipOutputStream,如果需要,我们该怎么做?这是我们之前使用字节数组方法时的代码:
byte[] pdfBody = restTemplate.getForObject(uri, byte[].class);
zos.write(pdfBody);
来自日志的堆栈跟踪如下。有趣的是,它在日志中显示 404 错误,但在 Chrome 开发者工具控制台中显示 500 错误。
2021-10-11 11:49:50.829 [http-nio-8080-exec-7] DEBUG u.c.g.dao.rest.RestContentDAO - loading document :: uri = /notice/5218192/version/1/supplier-id :: httpEntity = <{Cookie=[SessionID=null], Content-Type=[text/xml]}>
2021-10-11 11:49:50.906 [http-nio-8080-exec-7] ERROR u.c.g.a.c.BundleSummaryController - error during print pdf for a single notice
org.springframework.web.client.HttpClientErrorException: 404 null
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:79)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:775)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:728)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:684)
at uk.co.getBundlePdfAsZip(NoticesBundleServiceImpl.java:334)
at uk.co.BundleSummaryController.getNoticePdf(BundleSummaryController.java:248)
at uk.co.BundleSummaryController$$FastClassBySpringCGLIB$$e2e72224.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:69)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
at uk.co.BundleSummaryController$$EnhancerBySpringCGLIB$$851a488.getNoticePdf(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:877)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:783)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:101)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at uk.co.UpdateSavedRequestFilter.doFilterInternal(UpdateSavedRequestFilter.java:43)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at uk.co.auth.PreAuthFilter.doFilterInternal(PreAuthFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at uk.co.auth.BasicAuthModificationFilter.doFilterInternal(BasicAuthModificationFilter.java:38)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:146)
at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:81)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:496)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:650)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
解决方案
推荐阅读
- c# - 什么会导致 InitializeComponent 方法出错?
- javascript - 引导模式弹出窗口打开时无法关注文本框
- mule - 如何在 Mule 4 中将字符串转换为驼峰式大小写
- cloudera - 哪个 Cloudera 版本支持 YARN 节点标签
- html - 即使包含 Bootstrap 也无法正常工作
- sql - 到达日期时如何使特定行过期?
- php - 如何根据自定义分类法、开始日期和结束日期在 wordpress 中使用搜索输入来获取帖子?
- php - 在 Woocommerce 中根据购物车重量添加自定义结帐字段
- python - strptime 字符串到日期时间对象的转换
- linux - Linux 共享库依赖于 dlopen 使用 RTLD_LOCAL 打开的另一个共享库中的符号