首页 > 编程语言 >java下载zip文件

java下载zip文件

时间:2024-05-16 13:30:52浏览次数:27  
标签:java zip bos try catch new null response 下载

一、使用工具

* java.utils 下的ZipOutputStream
* java.net 的http请求工具 HttpURLConnection

二、 zip下载

1. 通过浏览器以附件的形式下载到客户端 
      思路:
        response 的write方法要写出一个byte[],所以我们需要从ZipStreamOutputStream中获取到byte[]。 在java中从io流中获取byte的办法就是将
        io流写到字节数组输出流中ByteArrayOutputStream(即内存中)。 代码如下:
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ZipStreamOutputStream zos = new ZipStreamOutputStream(bos)
        // 向zos中写数据  ...
        byte[] data = bos.toByteArray();
      分析数据流流向如下: 
        图片字节数据byte[](jpg)  -->  ZipStreamOutputStream -->   ByteArrayOutputStream -> byte[](zip)
2. 下载到服务器文件目录下
      分析数据流流向如下:  
        图片字节数据byte[](jpg)  -->  ZipStreamOutputStream -->   FileOutputStream -> File(zip)

三、 注意点

1. 在向ZipOutputStream中写完数据后,必须马上关闭ZipOutputStream,否则zip文件会损坏
2. 对于包装流,关闭流的顺序问题
  一层套一层的包装流,关闭顺序一定是先关闭外层包装流,然后再关闭内层的流,否则会文件损坏,而且在关闭外层流的时候会报流已经关闭异常

四、 实践代码

` /**
 * 图像下载接口, 返回base64编码的图像信息
 *
 * @param response
 * @param imgType
 * @throws IOException
 */
@GetMapping("/getImage")
public void imageDownloadServer(HttpServletResponse response, String imgType) throws IOException {
    response.setContentType("text/plain");
    ServletOutputStream outputStream = response.getOutputStream();
    BASE64Encoder encoder = new BASE64Encoder();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    File file = null;
    if ("F".equals(imgType)) {
        file = new File("C:\\Users\\cheva\\Desktop\\票样\\1.jpg");
    } else {
        file = new File("C:\\Users\\cheva\\Desktop\\票样\\2.jpg");
    }
    InputStream fis = new FileInputStream(file);
    int len = -1;
    byte[] buff = new byte[1024];
    while ((len = fis.read(buff)) != -1) {
        bos.write(buff, 0, len);
    }
    bos.flush();
    String base64 = encoder.encode(bos.toByteArray());
    fis.close();
    bos.close();
    outputStream.write(base64.getBytes(StandardCharsets.UTF_8));
    outputStream.flush();
    outputStream.close();
}


/**
 * 以附件的形式下载到客户端
 * @param request
 * @param response
 */
@GetMapping("/download")
public void dowload(HttpServletRequest request, HttpServletResponse response) {
    ByteArrayOutputStream bos = null;
    ZipOutputStream zipOutputStream = null;
    String outName = "my.zip";

    // 1. 向ZipOutputStream中写入数据。 流的走向: 数据字节 -> ZipOutputStream -> ByteArrayOutputStream
    // 注意: 在向ZipOutputStream中写完数据后,必须马上关闭ZipOutputStream,否则zip文件会损坏
    /**
     * 如下代码下载的zip文件会损坏
     * try {
     *             response.setContentType("application/zip");
     *             response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(outName, "UTF-8"));
     *             bos = new ByteArrayOutputStream();
     *             zipOutputStream = new ZipOutputStream(bos);
     *             packageZipStream("0011", zipOutputStream);
     *             outputStream = response.getOutputStream();
     *             outputStream.write(bos.toByteArray());
     *         } catch (Exception e) {
     *             e.printStackTrace();
     *         } finally {
     *             if (zipOutputStream != null) {
     *                 try {
     *                     zipOutputStream.close();
     *                 } catch (Exception e) {
     *                     System.out.println("流关闭异常");
     *                 }
     *             }
     *             if (bos != null) {
     *                 try {
     *                     bos.close();
     *                 } catch (Exception e) {
     *                     System.out.println("流关闭异常");
     *                 }
     *             }
     *         }
     *   原因在于在使用respose输出字节数组的时候,zipoutputstream还没有关闭,导致文件损坏,代码应该如下
     */

    try {
        bos = new ByteArrayOutputStream();
        zipOutputStream = new ZipOutputStream(bos);
        packageZipStream("0011", zipOutputStream);
    } catch (Exception e) {
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        try {
            ServletOutputStream os = response.getOutputStream();
            os.write(e.getMessage().getBytes());
            os.flush();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    } finally {
        // 注意: 像这种一层套一层的包装流,关闭顺序一定是先关闭外层包装流,然后再关闭内层的流,否则会文件损坏,而且在关闭外层流的时候会报流已经关闭异常
        if (zipOutputStream != null) {
            try {
                zipOutputStream.close();
            } catch (Exception e) {
                System.out.println("zip输出流关闭异常");
            }
        }
        if (bos != null) {
            try {
                bos.close();
            } catch (Exception e) {
                System.out.println("流关闭异常");
            }
        }
    }

    // 2. 响应数据
    try {
        response.setContentType("application/zip");
        response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(outName, "UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(bos.toByteArray());
        outputStream.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


/**
 * 下载到服务器本地文件夹
 * @param response
 */
@GetMapping("/downloadLoc")
public void downloadLoc(HttpServletResponse response) {
    FileOutputStream fis = null;
    ZipOutputStream zipOutputStream = null;
    try {
        File file = new File("D:\\Compressed\\my.zip");

        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdir();
        }
        fis = new FileOutputStream(file);
        zipOutputStream = new ZipOutputStream(fis);
        packageZipStream("0011", zipOutputStream);
    } catch (Exception e) {
        response.setContentType("text/html");
        response.setCharacterEncoding("UTF-8");
        try {
            ServletOutputStream os = response.getOutputStream();
            os.write(e.getMessage().getBytes());
            os.flush();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
    } finally {
        if (zipOutputStream != null) {
            try {
                zipOutputStream.close();
            } catch (Exception e) {
                System.out.println("流关闭异常");
            }
        }
        if (fis != null) {
            try {
                fis.close();
            } catch (Exception e) {
                System.out.println("流关闭异常");
            }
        }
    }
}


/**
 * 请求图片服务获取图像并写入到zip输出流中
 * @param imgId
 * @param zos
 */
private void packageZipStream(String imgId, ZipOutputStream zos) {
    String path = null;
    try {
        if (zos == null || imgId == null) {
            return;
        }
        // 1.  向zip输出流写入文件(ZipEntry), 如果有多个就循环下面五行代码。 注意: 如果文件重名,会ZipOutputStream会抛出ZipException
        path = imgId + File.separator + "正面.jpg";
        zos.putNextEntry(new ZipEntry(path));
        // 获取要写入ZipEntry的内容
        byte[] data = downloadImageFromURL("http://localhost:8098/chat-server/test/getImage?imgType=F");
        zos.write(data, 0, data.length);
        zos.closeEntry();

        path = imgId + File.separator + "反面.jpg";
        zos.putNextEntry(new ZipEntry(path));
        data = downloadImageFromURL("http://localhost:8098/chat-server/test/getImage?imgType=B");
        zos.write(data, 0, data.length);
        zos.closeEntry();
    } catch (Exception e) {
            if (e instanceof ZipException) {
                throw new RuntimeException(path + "重名,只进行一次下载处理");
            } else {
                throw new RuntimeException(e.getMessage());
            }

    }
}


/**
 * java HttpURLConnection作为客户端下载图像
 * @param urlPath
 * @return
 */
private byte[] downloadImageFromURL(String urlPath) {
    HttpURLConnection conn = null;
    InputStream is = null;
    byte[] data = null;
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    try {
        URL url = new URL(urlPath);
        conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(6000);
        conn.setDoInput(true);
        is = conn.getInputStream();
        if (conn.getResponseCode() == 200) {
            // 读取响应的输入流到字节输出流
            byte[] buff = new byte[1024];
            int len = -1;
            while ((len = is.read(buff)) != -1) {
                bos.write(buff, 0, len);
            }
            bos.flush();
            data = bos.toByteArray();
            BASE64Decoder decoder = new BASE64Decoder();
            data = decoder.decodeBuffer(new String(data));
        } else {
            data = null;
        }
    } catch (Exception e) {
            throw new RuntimeException("连接服务器异常");

    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (bos != null) {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return data;
}`

标签:java,zip,bos,try,catch,new,null,response,下载
From: https://www.cnblogs.com/chevalyang/p/18195681

相关文章

  • Windows 2019 2022 语言包下载地址
      2019大语言包 https://software-static.download.prss.microsoft.com/pr/download/17763.1.180914-1434.rs5_release_SERVERLANGPACKDVD_OEM_MULTI.iso https://software-download.microsoft.com/download/pr/17763.1.180914-1434.rs5_release_SERVERLANGPACKDVD_OEM_......
  • 西门子PLC+其它品牌PLC固件下载
    最低固件版本,S7-1200系列PLC从V3.0.2,S7-1500系列PLC从V1.8.1开始,目前已经全系列完整更新到最新版本。日后官方发布新版更新时本人亦会及时跟进更新。下载地址:https://url21.ctfile.com/d/12807121-18737887-637dff访问密码:7635各固件名称均以对应的产品订货号开头,后带的Vxx.xx......
  • JavaSE入门学习
    Java入门学习目录Java入门学习Java特征和优势Java三大版本开发环境搭建JDK下载及安装配置环境变量HelloWorld及简单语法规则使用IDE开发1.创建一个Java项目(IDEA)2.在该项目src目录下new一个class文件3.编辑代码4.运行代码Java特征和优势简单性面向对象可移植性高性能......
  • python3.8下载过程
    python网址:https://www.python.org/ 下载——————————————选downloads下的windows 稍微等待一会后进入此界面 向下滑,找到3.8.0(python版本并不是按顺序排列的) 选择适合自己的版本下载——————其中X86适用于32系统,X86-64适合64的web-based:透过网......
  • Jmeter下载安装教程(含汉化)
    参考教程:https://www.cnblogs.com/chenxiaomeng/p/9671443.html 注:Jmeter需要Javajdk的支持 ——下载官网地址:http://jmeter.apache.org/download_jmeter.cgi下载binaries下的zip文件(有说需要配置环境变量的,不过我没配也能跑) 汉化(永久)在Jmeter的bin目录下找到 ......
  • 在Linux中,如何进行Java应用性能调优?
    在Linux环境中进行Java应用程序的性能调优是一个多步骤的过程,涉及到监控、分析和调整多个层面的配置。以下是进行Java应用性能调优的一些关键步骤和策略:1.监控和分析工具的使用JVM监控工具:利用jstat,jmap,jstack,和jconsole等JDK自带的工具,以及更高级的工具如VisualVM、JP......
  • Docker Desktop部署微软微服务Dapr(Redis+Zipkin+Placement)
    DockerDesktop部署微软微服务Dapr(Redis+Zipkin+Placement)说明系统:Windows11专业版23H2Docker:DockerDesktopv4.29.0+本文为开发环境学习和测试使用安装DaprCLI使用MSI安装程序安装每个DaprCLI的发布版本还包括一个适用于Windows的安装程序。您可以手动下......
  • JavaScript object array sort by string bug All In One
    JavaScriptobjectarraysortbystringbugAllInOnebug//purestringsarray,sortOK✅letarr=["banana","strawberry","apple"];JSON.stringify(arr.sort());//'["apple","banana","strawbe......
  • 解决新浪微博图床 403 批量下载图片等资源(以 MMChat 数据集为例)
    目录1.代码2.举一反三1.代码该Python脚本可多线程地批量下载新浪图床图片,每次下载会检查哪些图片已下载并过滤已下载的图片。importosimportrequestsfromconcurrent.futuresimportThreadPoolExecutor,as_completedimportloggingimporttimefromtqdmimport......
  • JAVA版的代码生成器gen
    自己安装方式dockerpullregistry.cn-hangzhou.aliyuncs.com/tanghc/gen:latest 下载完毕后,执行 dockerrun--namegen--restart=always\-p6969:6969\-eJAVA_OPTS="-server-Xms64m-Xmx64m-DLOCAL_DB=/opt/gen/gen.db"\-v/opt/gen/:/opt/gen/\......