Java 马上就拉上拉链
我需要生成一个ZIP文件,其中包含来自servlet的动态数据。我将ServletOutputSream传递给ZipOutputStream构造函数,它会这样做,并正确地将ZIP发送到客户端。当ZIP结果很大时,servlet需要花费大量时间来回答问题。我想首先创建ZIP,然后发送它 我创建了一个helper类来包装ZipOutputStream 我需要在调用flush方法时,立即发送已经生成的ZIP片段。我该怎么做Java 马上就拉上拉链,java,servlets,zip,Java,Servlets,Zip,我需要生成一个ZIP文件,其中包含来自servlet的动态数据。我将ServletOutputSream传递给ZipOutputStream构造函数,它会这样做,并正确地将ZIP发送到客户端。当ZIP结果很大时,servlet需要花费大量时间来回答问题。我想首先创建ZIP,然后发送它 我创建了一个helper类来包装ZipOutputStream 我需要在调用flush方法时,立即发送已经生成的ZIP片段。我该怎么做 public class ZIPResponse { private
public class ZIPResponse {
private ZipOutputStream out;
private HttpServletResponse response;
private boolean isFirstEntry;
private ConnectionManager con;
public ZIPResponse(ConnectionManager con, OutputStream out) throws IOException {
this.out = new ZipOutputStream(out);
isFirstEntry = true;
this.con = con;
}
public ZIPResponse(ConnectionManager con, HttpServletResponse response) throws IOException {
this(con, response.getOutputStream());
this.response = response;
response.setCharacterEncoding("ISO-8859-1");
sendNewEntry("con");
flush();
}
public void sendNewEntry(String dataName) throws IOException {
if (isFirstEntry) {
isFirstEntry = false;
} else {
out.closeEntry();
}
out.putNextEntry(new ZipEntry(dataName));
}
public void sendData(String dataName, String data) throws IOException {
sendNewEntry(dataName);
sendData(data);
}
public void sendData(byte[] bytes) throws IOException {
out.write(bytes);
flush();
}
public void sendData(String data) throws IOException {
sendData(data.getBytes());
}
public void sendAndCloseData(String dataName, String data) throws IOException {
sendNewEntry(dataName);
sendData(data);
close();
}
private void sendDataFile(String dataName, DataTransformer dt)
throws IOException, SQLException {
sendNewEntry(dataName);
dt.sendResultSet(this);
}
public void sendDataFile(String dataName, ResultSet data, String[] columnsRestriction) throws IOException,
SQLException {
RestrictedDataTransformer dt = new RestrictedDataTransformer(data, columnsRestriction);
sendDataFile(dataName, dt);
}
public void sendDataFile(String dataName, ResultSet data) throws IOException,
SQLException {
DataTransformer dt = new DataTransformer(data);
sendDataFile(dataName, dt);
}
public void sendDataFile(String dataName, PreparedStatement p) throws
SQLException, IOException {
ResultSet data = p.executeQuery();
sendDataFile(dataName, data);
}
public void sendDataFile(String dataName, String SQL, String[] columnsRestricted)
throws DBException, SQLException, IOException {
ResultSetStatement st = new ResultSetStatement(con, SQL);
ResultSet valores = st.executeQuery();
try {
sendDataFile(dataName, valores, columnsRestricted);
} finally {
valores.close();
}
}
public void sendDataFile(String dataName, String SQL) throws DBException, SQLException, IOException {
ResultSetStatement st = new ResultSetStatement(con, SQL);
ResultSet valores = st.executeQuery();
try {
sendDataFile(dataName, valores);
} finally {
valores.close();
}
}
public void sendAndCloseDataFile(String dataName, ResultSet data) throws
SQLException, IOException {
sendDataFile(dataName, data);
close();
}
public void sendAndCloseDataFile(String dataName, String SQL) throws DBException, SQLException, IOException {
sendDataFile(dataName, SQL);
close();
}
public void close() throws IOException {
sendNewEntry("OK");
out.closeEntry();
out.close();
flush();
}
public void flush() throws IOException {
out.flush();
response.flushBuffer();
}
}
如果您的客户端对接收内容灵活,GZIP将更好地用于流式压缩。如果您的客户端对接收内容灵活,GZIP将更好地用于流式压缩。我想您的问题是在完成zip创建之前将zip内容发送给响应。是的,你可以通过缓冲来实现
对于缓冲,请遵循我猜您的问题是在完成zip创建之前将zip内容发送到response。是的,你可以通过缓冲来实现
对于缓冲,请遵循以下步骤以下是我的实现:
String realpath = getServletContext().getRealPath("/");
response.setContentType("application/zip");
response.setHeader("Content-Disposition","attachment; filename="+fi.replace('/', '-')+"_"+ff.replace('/', '-')+".zip");
ServletOutputStream out = null;
ZipOutputStream zipfile = null;
try{
List<Object[]> cfdis = /*my hibernate criteria source, your Database?*/
out = response.getOutputStream();
zipfile = new ZipOutputStream(out);
ZipEntry zipentry = null;
for(Object[] cfdi:cfdis){
zipentry = new ZipEntry(cfdi[1].toString()+".xml");
zipfile.putNextEntry(zipentry);
InputStream in = new FileInputStream(new File(realpath+cfdi[0].toString()));
byte[] bytes = new byte[FILEBUFFERSIZE];
int bytesRead;
while ((bytesRead = in.read(bytes)) != -1) {
zipfile.write(bytes, 0, bytesRead);
}
}
}catch(...){}
finally{
zipfile.close();
out.close();
}
我希望您觉得这很有用。以下是我的实现:
String realpath = getServletContext().getRealPath("/");
response.setContentType("application/zip");
response.setHeader("Content-Disposition","attachment; filename="+fi.replace('/', '-')+"_"+ff.replace('/', '-')+".zip");
ServletOutputStream out = null;
ZipOutputStream zipfile = null;
try{
List<Object[]> cfdis = /*my hibernate criteria source, your Database?*/
out = response.getOutputStream();
zipfile = new ZipOutputStream(out);
ZipEntry zipentry = null;
for(Object[] cfdi:cfdis){
zipentry = new ZipEntry(cfdi[1].toString()+".xml");
zipfile.putNextEntry(zipentry);
InputStream in = new FileInputStream(new File(realpath+cfdi[0].toString()));
byte[] bytes = new byte[FILEBUFFERSIZE];
int bytesRead;
while ((bytesRead = in.read(bytes)) != -1) {
zipfile.write(bytes, 0, bytesRead);
}
}
}catch(...){}
finally{
zipfile.close();
out.close();
}
我希望您觉得这很有用。您的web服务器和客户端需要支持发送分块响应,因为在发送数据之前,长度是未知的。您的web服务器和客户端需要支持发送分块响应,因为在发送数据之前,长度是未知的。我看不出这是如何解决OP的问题的ZipOutputStream在内存中完全缓冲到最后一位的问题。你能在这一部分再详细说明一下吗?你不是在内存中存储zip的内容,只是垃圾收集的小字节[],只有流,容器正在发送块,因为我们没有通过ServletOutputStream提供ZipOutputStream的java ee容器中定义的响应长度大小。我看不出这是如何解决OP的问题的,ZipOutputStream在内存中被完全缓冲到最后一位。你能详细说明一下吗?你不会在内存中存储zip的内容,只是垃圾收集的小字节[],只有流,容器发送块,因为我们没有通过ServletOutputStream提供ZipOutputStream的java ee容器中定义的响应长度大小。