美文网首页
java下载多个文件并打成压缩包

java下载多个文件并打成压缩包

作者: 不要夜空霓虹的繁荣 | 来源:发表于2021-01-11 19:23 被阅读0次
    BatMan

    先放一张自己喜欢的图片,写着有劲。

    ——需求:

    简单的说下需求,下载多个文件,并按照自定义的需求把文件放在不同文件夹下,并自定义每个文件的名称,

    1.数据库

    只说重点两个字段。
    name,是在页面上显示的文件的名字。
    document_url,是此文件存在于你的硬盘上真实的文件名,我是以UUID命名的。


    数据库

    2.实现类

    这一步,是我项目的具体需求,不重要,重要的就是要凑成一个 Map ,也就是我下面的注释部分是主要的。

    /**
     *自恋一下
         * 汤氏多文件下载
         * @param ids
         * 组合一个Map<String, Map<String,File>> files
         * 第一层 map 的 key 为最外层的文件夹的名字,
         * 第二层 map 的 key 为这个文件的自定义路径,如:最外层文件夹/文件夹A/文件夹A1/文件.jpg,
         * zip打包后会自动分层。
         * 第二层的 value 是真实存在的文件
         */
        @Override
        public void tangDownloadFiles(List<Long> ids,HttpServletResponse response) {
            List<PlanDocumentRecordsEntity> list = queryFactory.selectFrom(qPlanDocumentRecords).where(qPlanDocumentRecords.deleteStatus.eq(1).and(qPlanDocumentRecords.id.in(ids)).and(qPlanDocumentRecords.catalogOrFile.eq(2))).fetch();
            //存放文件及其文件的父路径
            Map<String,File> fileMap = new HashMap<>();
    
            for (PlanDocumentRecordsEntity entitie : list){
                String str = entitie.getDocumentUrl();
                String s = "";
                if (entitie.getParentId()!=0){
                    String url = this.getParentName(entitie.getParentId(),s)+str;
                    File file = new File(upLoadFilePath+str);
                    fileMap.put(url,file);
                }
            }
            
            Map<String, Map<String,File>> files = new HashMap<>();
            String planName = "计划";
            if (ids!=null && ids.size()>0){
                //文件件的最外层为此计划的名字
                planName = queryFactory.select(qPlanInfo.name).from(qPlanInfo).leftJoin(qPlanDocumentRecords).on(qPlanDocumentRecords.planId.eq(qPlanInfo.id)).where(qPlanDocumentRecords.id.eq(ids.get(0))).fetchFirst();
            }
            files.put(planName,fileMap);
            //开始打包
            this.zipMultipleFiles(files,response);
        }
    

    其实也是参考的网上别人的写的,但是找不到那个链接了,就不加了
    然后我是根据自己的需求所改动了一下。

    以下为重要部分。

    public void zipMultipleFiles(Map<String, Map<String,File>>files, HttpServletResponse response) {
            //下载的压缩包的名
            String downloadFilename = UUID.randomUUID().toString().replace("-", "");
            System.out.println(downloadFilename);
            ZipOutputStream zos = null;
            InputStream in = null;
            try {
                response.setContentType("application/octet-stream");// 指明response的返回对象是文件流
                response.setHeader("Content-Disposition", "attachment;filename=" + downloadFilename);// 设置在下载框默认显示的文件名
                downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");
                zos = new ZipOutputStream(response.getOutputStream());
                for (Map.Entry<String, Map<String,File>> entry : files.entrySet()) {
                    if (entry.getValue()!=null&&entry.getValue().size()!=0) {
                        //开始循环
                        for (Map.Entry<String,File> fileEntry : entry.getValue().entrySet()){
                            String key = fileEntry.getKey();
                            int i =key.lastIndexOf("/");
                            if (i==-1){
                                i=0;
                            }
                            //此 url 是自己组合的在zip包内的该文件的目录结构,不包括最外层的文件夹,因为最外层的文件夹,是我自己固定好的,也就是下载完的压缩包解压后会有一个固定的最外层的文件夹。(注意并不是文件在硬盘上的实际目录结构,实际的所有的文件都放在了同一个文件夹下了)
                            String url = fileEntry.getKey().substring(0,i);
                            //自定义压缩包内每个文件的名字
                            //这步就是要把文件换成自己想要展示出来的名字,也就是上边数据库中 name 字段。
                            String newFileName = queryFactory.select(qPlanDocumentRecords.name).from(qPlanDocumentRecords).where(qPlanDocumentRecords.documentUrl.eq(fileEntry.getValue().getName())).fetchFirst();
                            //打压缩包
                            //entry.getKey()就是上述所说的最外层的文件夹,也是自己定义的。
                            zos.putNextEntry(new ZipEntry(
                                    entry.getKey()+File.separator+ url + File.separator + newFileName));
                            //文件路径放入流
                            in = new FileInputStream(fileEntry.getValue().getPath());
                            byte[] buffer = new byte[1024];
                            int r = 0;
                            while ((r = in.read(buffer)) != -1) {
                                zos.write(buffer, 0, r);
                            }
                            in.close();
                        }
                        zos.flush();
                    }
                }
            } catch (Exception e) {
                log.error("zipFiles error!!", e);
            } finally {
                if (zos!=null) {
                    try {
                        zos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    try {
                        zos.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (in!=null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    

    至此你就成功了,上述毕竟是我根据我自己的业务逻辑所写,可能有些代码并用不到,但是最重要的部分我也告诉大家了,所以也可以自己发挥了。

    最后以美好的心情结尾

    迪丽热巴

    相关文章

      网友评论

          本文标题:java下载多个文件并打成压缩包

          本文链接:https://www.haomeiwen.com/subject/gfndaktx.html