Liferay Portlet下载Excel时获取PortletOutputStream抛出异常求助
Liferay Portlet Excel下载:解决
getPortletOutputStream()抛出的IllegalStateException 在Liferay Portlet中实现Excel下载时,调用resourceResponse.getPortletOutputStream()抛出异常:
java.lang.IllegalStateException: Unable to obtain OutputStream because Writer is already in use
原因分析
- 错误使用字符流处理二进制文件:Excel属于二进制格式,代码中用
InputStreamReader、OutputStreamWriter这类字符流读写,会破坏文件结构,同时可能触发Portlet容器提前初始化Writer,导致后续无法获取OutputStream。 - 响应头拼写错误:
Content-disposition属性中的atachment是拼写错误,正确应为attachment,错误的响应头可能引发容器异常处理逻辑,间接导致Writer被占用。
解决方案
- 改用字节流直接复制文件内容到输出流,避免字符转换操作。
- 修正
Content-disposition的拼写错误。 - 确保代码中没有其他地方提前获取
ResourceResponse的Writer(比如调用getWriter()方法)。
修正后的代码
public static void descargaFichero(ResourceRequest resourceRequest, ResourceResponse resourceResponse) throws Exception { HttpServletRequest request = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(resourceRequest)); OutputStream outputStream = null; InputStream is = null; File tempFile = null; try { String idDescarga = request.getParameter("id-descarga"); String rutaFicheroDescarga = Encriptador.decrypt(ConstantesFlujos.CLAVE_ENCRIPTADO_JSON, idDescarga); String extension = FileUtil.getExtension(rutaFicheroDescarga); String nombreArchivo = String.format("%s%s.%s", ConstantesFlujos.PREFIJO_NOMBRE_FICHERO_RENOVACION, fechaDesglosada(), extension); if(GestorLog.isInfoEnabled(clase)){ GestorLog.info(clase, String.format("Descargando fichero temporal: '%s' a '%s'", rutaFicheroDescarga, nombreArchivo)); } if (extension.equalsIgnoreCase("xls")) { resourceResponse.setContentType("application/vnd.ms-excel"); } else { resourceResponse.setContentType("application/octet-stream"); } // 修正拼写错误:atachment -> attachment ((PortletResponse) resourceResponse).addProperty("Content-disposition", String.format("attachment; filename=%s", nombreArchivo)); tempFile = new File(rutaFicheroDescarga); outputStream = resourceResponse.getPortletOutputStream(); is = new FileInputStream(tempFile); // 用字节流直接复制,避免字符转换 byte[] buf = new byte[8192]; int c = 0; while ((c = is.read(buf, 0, buf.length)) > 0) { outputStream.write(buf, 0, c); outputStream.flush(); } } catch(Exception e){ GestorLog.error(clase, "Error en el metodo descargaFichero: " + e.getMessage()); throw e; } finally { // 按顺序关闭资源:先关闭输入流,再关闭输出流 if (is != null) { is.close(); } if (outputStream != null) { outputStream.close(); } if (tempFile != null) { tempFile.delete(); } } }
内容的提问来源于stack exchange,提问作者Daniel Rodríguez Bravo
相关产品推荐
相关产品推荐

