我需要使用来 self 的基于 java 的 Web 系统的数据生成一堆 xml 文件,这些文件代表另一个基于 XML 的系统的完整导出。此类系统稍后将接受此导入。
我的方法是在内存中创建所有文件,然后将每个文件作为条目保存到内存中的 zip 中,稍后将其提供给客户端。
数据流工作正常,但不知何故输出是一个空白文件。我想我弄错了输出流结构
这是我可能会出错的部分: ...
//ZIP creation in server memory
ByteArrayOutputStream datosEnMemoria = new ByteArrayOutputStream();
ZipOutputStream zipped_out = new ZipOutputStream(datosEnMemoria)
...
//close and zip entry
xmlData.append(Tangonet.terminarCargaRegistros());
byte[] xmlBinData = xmlData.toString().getBytes();
zipped_out.write(xmlBinData, 0, xmlBinData.length);
zipped_out.closeEntry();
}
byte[] zipped_out_size = zipped_out.toString().getBytes();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=cierresZ_a_tangonet" + java.time.LocalDate.now() + ".zip");
response.setHeader("Content-length", "" + zipped_out_size.length);
response.setHeader("Content-Type", "application/zip");
response.setHeader("Content-Type", "application/octet-stream");
response.setHeader("Content-Transfer-Encoding", " binary");
//closing zip and send it to client
zipped_out.flush();
zipped_out.close();
// out.flush();
// out.close();
这是完整的代码:
@RequestMapping(value = "/cierreZ/exportar", method = RequestMethod.GET)
public void cierreZExportar(@ModelAttribute InformesFinancierosForm informesFinancierosForm, HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession(true);
String fechaInicio = null;
String fechaFin = null;
if (session.getAttribute("mesActual") != null) {
informesFinancierosForm.setFechaInicio("01-" + informesFinancierosForm.getMes());
informesFinancierosForm.setFechaFin(new SimpleDateFormat("dd-MM-yyyy").format(DateUtil.getUltimoDiaDelMes(DateUtil.traduceDateDate((String) session.getAttribute("fechaIni")))));
fechaInicio = informesFinancierosForm.getFechaInicio();
fechaFin = informesFinancierosForm.getFechaFin();
} else {
fechaInicio = (String) session.getAttribute("fechaIni");
fechaFin = (String) session.getAttribute("fechaFin");
}
if (informeService.isRangoFechaValido(informesFinancierosForm.getSalasSeleccionadas(), fechaInicio)) {
if (!(fechaInicio.compareTo("") == 0) || (fechaFin.compareTo("") == 0)
|| informesFinancierosForm.getSalasSeleccionadas().length == 0) {
// ServletOutputStream out = response.getOutputStream();
List<InformeCierreZItemForm> listadoInfCierreZ = cierreZService.getCierres(informesFinancierosForm.getSalasSeleccionadas(), fechaInicio, fechaFin);
//ZIP creation in server memory
ByteArrayOutputStream datosEnMemoria = new ByteArrayOutputStream();
ZipOutputStream zipped_out = new ZipOutputStream(datosEnMemoria);
//filling zip with static xml files
for (int i = 0; i < Tangonet.documentos_estaticos_tangonet.length; i++) {
ZipEntry xmlFile = new ZipEntry(Tangonet.documentos_estaticos_tangonet[i][0] + ".xml");
zipped_out.putNextEntry(xmlFile);
StringBuilder xmlData = new StringBuilder();
xmlData.append(Tangonet.documentos_estaticos_tangonet[i][1]);
byte[] xmlBinData = xmlData.toString().getBytes();
zipped_out.write(xmlBinData, 0, xmlBinData.length);
zipped_out.closeEntry();
}
//filling zip with dynamic xml files
for (int i = 0; i < Tangonet.documentos_dinamicos_tangonet.length; i++) {
//dynamic xml creation
ZipEntry xmlFile = new ZipEntry(Tangonet.documentos_dinamicos_tangonet[i][0] + ".xml");
zipped_out.putNextEntry(xmlFile);
//xml schema
StringBuilder xmlData = new StringBuilder();
xmlData.append(Tangonet.documentos_dinamicos_tangonet[i][1]);
//xml data rows
for (InformeCierreZItemForm informeCierreZActual : listadoInfCierreZ) {
Sala salaActual = informeCierreZActual.getSala();
CierrezList CierresZ = cierreZService.getCierresZ(salaActual, fechaInicio, fechaFin);
//fiscal data in rows
Tangonet datosFiscalesCierrezActual = tangonetDatos.getDatosFiscales(salaActual);
for (Cierrez cierreActual : CierresZ) {
if (Tangonet.documentos_dinamicos_tangonet[i][0].equals("Comp_de_Facturación_para_Cobranza_Centralizada___GVA12")) {
xmlData.append(datosFiscalesCierrezActual.crearRegistroGVA12(cierreActual));
} else {
xmlData.append(datosFiscalesCierrezActual.crearRegistroGVA42(cierreActual));
}
}
}
//close and zip entry
xmlData.append(Tangonet.terminarCargaRegistros());
byte[] xmlBinData = xmlData.toString().getBytes();
zipped_out.write(xmlBinData, 0, xmlBinData.length);
zipped_out.closeEntry();
}
byte[] zipped_out_size = zipped_out.toString().getBytes();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=cierresZ_a_tangonet" + java.time.LocalDate.now() + ".zip");
response.setHeader("Content-length", "" + zipped_out_size.length);
response.setHeader("Content-Type", "application/zip");
response.setHeader("Content-Type", "application/octet-stream");
response.setHeader("Content-Transfer-Encoding", " binary");
//closing zip and send it to client
zipped_out.flush();
zipped_out.close();
// out.flush();
// out.close();
}
}
}
最佳答案
Zip 文件可能很大,因此不要在内存中生成它。直接写给客户。
另外:
不要设置
Content-Type
三次。它只能有一个值。不要指定
Content-Transfer-Encoding
。这是电子邮件 header ,而不是 HTTP header 。由于您要进行流式传输,因此请勿指定
Content-length
。
// headers must be set before streaming
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;filename=cierresZ_a_tangonet" + java.time.LocalDate.now() + ".zip");
// stream straight to client
ZipOutputStream zipped_out = new ZipOutputStream(response.getOutputStream());
// Add zip entries and data here:
// Loop:
// zipped_out.putNextEntry(...)
// Generate XML, writing it straight to zipped_out
// Remember to flush any streams/writers wrapped around zipped_out
// Do not close zipped_out or wrappers of it
// If that cannot be prevented, use a CloseShieldOutputStream (from Commons IO)
// No need to call zipped_out.closeEntry()
// make sure to finish the zip stream
zipped_out.finish();
关于java - 提供服务器中生成并存储在内存中的 zip 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58597942/