//批量下载文件并打包
public static void downLoadZipAllFile(HttpServletRequest request, HttpServletResponse response, List<Map<String,String>> maps) {
OutputStream outp = null;
ZipOutputStream zos = null;
BufferedInputStream bis = null;
String downloadZipDir = "D:/ftpHome/downloadZip";
try {
outp = response.getOutputStream();
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html; charset=UTF-8"); //设置编码字符
response.setContentType("application/octet-stream"); //设置内容类型为下载类型
// response.setContentType("application/zip");// 定义输出类型
String timeSuffix = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String zipFilePath = downloadZipDir + "/" + timeSuffix + "_DataFile.zip";
String filedisplay = zipFilePath;
if (filedisplay.indexOf("/") >= 0) {
filedisplay = filedisplay.substring(filedisplay.lastIndexOf("/") + 1);
} else if (filedisplay.indexOf("\\") >= 0) {
filedisplay = filedisplay.substring(filedisplay.lastIndexOf("\\") + 1);
}
String agent = (String) request.getHeader("USER-AGENT");
// firefox
if (agent != null && agent.indexOf("MSIE") == -1) {
String enableFileName = "=?UTF-8?B?"
+ (new String(Base64.getBase64(filedisplay))) + "?=";
response.setHeader("Content-Disposition",
"attachment; filename=" + enableFileName);
} else {
filedisplay = URLEncoder.encode(filedisplay, "utf-8");
response.addHeader("Content-Disposition",
"attachment;filename=" + filedisplay);
}
try {
// File zip = new File(zipFilePath);
// if (!zip.exists()) {
// zip.createNewFile();
// }
zos = new ZipOutputStream(new FileOutputStream(zipFilePath));
for (Map<String, String> map : maps) {
String filePath = map.get("filePath");
String filename = map.get("fileName");
File file = new File(filePath);
if (file.exists()) {
zos.putNextEntry(new ZipEntry(filename));
zos.setEncoding("GBK");
bis = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[1024 * 64];
int i = 0;
while ((i = bis.read(b)) > 0) {
zos.write(b, 0, i);
}
zos.closeEntry();
bis.close();
String isDelete = request.getParameter("isDelete");
if ("1".equals(isDelete)) {
file.delete();
}
}
// else {
// outp.write("文件不存在!".getBytes("GBK"));
// }
}
zos.close();
InputStream ins = new FileInputStream(zipFilePath);
BufferedInputStream bins = new BufferedInputStream(ins);// 放到缓冲流里面
BufferedOutputStream bouts = new BufferedOutputStream(outp);
int bytesRead = 0;
byte[] buffer = new byte[8192];
// 开始向网络传输文件流
while ((bytesRead = bins.read(buffer, 0, 8192)) != -1) {
bouts.write(buffer, 0, bytesRead);
}
bouts.flush();// 这里一定要调用flush()方法
ins.close();
bins.close();
outp.close();
bouts.close();
} catch (Exception e) {
e.printStackTrace();
}
// finally {
// if (bis != null) {
// bis.close();
// bis = null;
// }
//// if (zos != null) {
//// zos.close();
//// zos = null;
//// }
//// if (outp != null) {
//// outp.close();
//// outp = null;
//// }
// }
} catch (IOException e) {
e.printStackTrace();
}
}
目前的效果是能在文件夹中看到压缩好的包,但是把这个zip包通过流的方式发送到浏览器,也就是利用response.getOutputStream,为啥弹出来的不是zip包,而是其中一个文件,并且文件中乱码,求各位大神教教呀!
谷歌浏览器乱码情况如下:
参考GPT:可能是因为你在设置response的ContentType时,同时设置了"text/html; charset=UTF-8"和"application/octet-stream"两种类型,导致输出的内容既不是html文本,也不是二进制流类型,而是一些混合的内容,从而导致浏览器无法正确处理文件类型。
你可以尝试修改代码,只保留设置"application/octet-stream"的内容类型,并删除设置"text/html; charset=UTF-8"的代码行。另外,也可以将写入Zip文件的编码方式设置为UTF-8,这样可以确保文件内容的正确性。下面是修改后的代码片段:
outp = response.getOutputStream();
response.setContentType("application/octet-stream");
String timeSuffix = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String zipFilePath = downloadZipDir + "/" + timeSuffix + "_DataFile.zip";
String filedisplay = zipFilePath;
if (filedisplay.indexOf("/") >= 0) {
filedisplay = filedisplay.substring(filedisplay.lastIndexOf("/") + 1);
} else if (filedisplay.indexOf("\\") >= 0) {
filedisplay = filedisplay.substring(filedisplay.lastIndexOf("\\") + 1);
}
String agent = (String) request.getHeader("USER-AGENT");
if (agent != null && agent.indexOf("MSIE") == -1) {
String enableFileName = "=?UTF-8?B?" + (new String(Base64.getBase64(filedisplay))) + "?=";
response.setHeader("Content-Disposition", "attachment; filename=" + enableFileName);
} else {
filedisplay = URLEncoder.encode(filedisplay, "utf-8");
response.addHeader("Content-Disposition", "attachment;filename=" + filedisplay);
}
try {
zos = new ZipOutputStream(new FileOutputStream(zipFilePath), Charset.forName("UTF-8"));
for (Map<String, String> map : maps) {
String filePath = map.get("filePath");
String filename = map.get("fileName");
File file = new File(filePath);
if (file.exists()) {
zos.putNextEntry(new ZipEntry(filename));
bis = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[1024 * 64];
int i = 0;
while ((i = bis.read(b)) > 0) {
zos.write(b, 0, i);
}
zos.closeEntry();
bis.close();
String isDelete = request.getParameter("isDelete");
if ("1".equals(isDelete)) {
file.delete();
}
}
}
zos.close();
InputStream ins = new FileInputStream(zipFilePath);
BufferedInputStream bins = new BufferedInputStream(ins);
BufferedOutputStream bouts = new BufferedOutputStream(outp);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = bins.read(buffer, 0, 8192)) != -1) {
bouts.write(buffer, 0, bytesRead);
}
bouts.flush();
ins.close();
bins.close();
outp.close();
bouts.close();
} catch (Exception e) {
e.printStackTrace();
}
该回答引用GPTᴼᴾᴱᴺᴬᴵ以及自己的分析思考,具体如下:
从你提供的代码中,我看到你在使用ZipOutputStream输出文件时设置了编码为GBK,而在设置Content-Type为application/octet-stream之后,却没有设置字符编码,这可能导致乱码的问题。可以尝试在设置Content-Type后,再设置一个Content-Disposition的header来指定文件名,同时指定编码为UTF-8,具体的代码如下例子。
例如:
response.setContentType("application/octet-stream"); //设置内容类型为下载类型
String filename = "example.zip";
response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + URLEncoder.encode(filename, "UTF-8"));
如果以上回答对您有所帮助,望采纳~谢谢
关于response.outputStream乱码的问题,我看到你上设置的是charset=UTF-8,但是压缩包的格式设置的是 zos.setEncoding("GBK");这里检查是不是这里的问题
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先,代码中有一个地方需要修改,就是设置编码字符的地方,应该改成:
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=\""
+ new String(filedisplay.getBytes("UTF-8"), "ISO8859-1") + "\"");
原来的代码是设置了两次response.setContentType
,第二次设置的是下载类型,但是这样会覆盖掉第一次设置的编码类型,所以应该删除掉第二次设置。另外,对于中文文件名,应该使用ISO8859-1编码,否则下载时中文文件名可能会出现乱码。
其次,关于文件乱码的问题,可能是因为在压缩文件时使用了zos.setEncoding("GBK")
指定了编码方式,但是在下载文件时并没有指定编码方式,所以可以将zos.setEncoding("GBK")
这一行代码删除试试。
最后,关于只下载其中一个文件的问题,可以将最后几行代码的while循环改成:
byte[] buffer = new byte[8192];
int len;
while ((len = ins.read(buffer)) > 0) {
outp.write(buffer, 0, len);
}
修改完之后,整个方法的代码应该是这样的:
public static void downLoadZipAllFile(HttpServletRequest request, HttpServletResponse response, List<Map<String,String>> maps) {
OutputStream outp = null;
ZipOutputStream zos = null;
BufferedInputStream bis = null;
String downloadZipDir = "D:/ftpHome/downloadZip";
try {
outp = response.getOutputStream();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream"); //设置内容类型为下载类型
String timeSuffix = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
String zipFilePath = downloadZipDir + "/" + timeSuffix + "_DataFile.zip";
String filedisplay = zipFilePath;
if (filedisplay.indexOf("/") >= 0) {
filedisplay = filedisplay.substring(filedisplay.lastIndexOf("/") + 1);
} else if (filedisplay.indexOf("\\") >= 0) {
filedisplay = filedisplay.substring(filedisplay.lastIndexOf("\\") + 1);
}
response.setHeader("Content-Disposition", "attachment; filename=\""
+ new String(filedisplay.getBytes("UTF-8"), "ISO8859-1") + "\"");
try {
zos = new ZipOutputStream(new FileOutputStream(zipFilePath));
for (Map<String, String> map : maps) {
String filePath = map.get("filePath");
String filename = map.get("fileName");
File file = new File(filePath);
if (file.exists()) {
zos.putNextEntry(new ZipEntry(filename));
bis = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[1024 * 64];
int i = 0;
while ((i = bis.read(b)) > 0) {
zos.write(b, 0, i);
}
zos.closeEntry();
bis.close();
String isDelete = request.getParameter("isDelete");
if ("1".equals(isDelete)) {
file.delete();
}
}
}
zos.close();
InputStream ins = new FileInputStream(zipFilePath);
BufferedInputStream bins = new BufferedInputStream(ins);
byte[] buffer = new byte[8192];
int len;
while ((len = ins.read(buffer)) > 0) {
outp.write(buffer, 0, len);
}
outp.flush();
} catch (Exception e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outp != null) {
try {
outp.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
如果我的回答解决了您的问题,请采纳!
response.setHeader("Content-Disposition", "attachment;filename=" + filename); // 告诉浏览器以附件的形式下载文件,并指定文件名称
只要以上一个响应头就够了,因为本身就是要二进制流下载文件,所以不需要在响应头中设置字符集
该回答引用于gpt与OKX安生共同编写:
根据您提供的代码和截图,您正在使用 Java 编写一个 Web 应用程序,下载并打包文件,并将其作为 ZIP 文件发送到浏览器。
我注意到您已经设置了 response.setContentType("application/octet-stream")
,这是一种通用的二进制流内容类型,因此它应该可以正确发送 ZIP 文件。但是,在您的屏幕截图中,我们可以看到您在浏览器中看到的似乎是一个具有随机字符的文本文件。这表明您正在尝试将 ZIP 文件作为文本文件发送,而不是正确地设置响应头以指示响应数据是二进制内容。
您可以尝试以下操作来解决这个问题:
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment;filename=download.zip");
response.getOutputStream().write(zipBytes);
response.getOutputStream().flush();
response.getOutputStream().close();
unzip -l download.zip