Spring boot 文件下载 文件压缩

文件下载

代码:

    @GetMapping("/download")
    public ResponseEntity<FileSystemResource> downloadFile(HttpServletRequest request) {

        // 获取上送参数 
        String currentPath  = request.getParameter("currentPath");
        String subPath  = request.getParameter("subPath");
        String fileName  = request.getParameter("fileName");
        String download  = request.getParameter("download");
        
        String dpath = "";
        String dname = "";
        boolean isfail = false;
        String msg = "";
        
        log.debug("下载文件请求参数: " + currentPath + " " + subPath + " " + fileName + " " + download);
        
        // 下载目录时, 检查  download 为1  , 压缩目录 root + currentPath + subPath 
        if (StringUtils.equals(download, "1")) {
            String tmppath  = FileUtil.contactPath(currentPath, subPath);
            String dirpath = FileUtil.contactPath(this.fileRoot, tmppath);
            String zipname = ".zip";
            
            if (StringUtils.isBlank(tmppath) || StringUtils.equals(tmppath, File.separator)) {
                // 当tmppath 为空时, 取名为 root 
                zipname = "root" + zipname;
            } else {
                String[] strs = tmppath.split(Matcher.quoteReplacement(File.separator));
                zipname = strs[strs.length - 1] + zipname;
            }
            
            // zip 文件保存路径 
            // 使用随机字符串生成路径
            String zippath = FileUtil.contactPath(this.download_root, UUID.randomUUID().toString());
            
            log.debug("开始压缩文件: " + dirpath + " " + zippath + " " + zipname);
            
            try {
                FileUtil.folder2zip(dirpath, zippath, zipname);
            } catch (Exception exp) {
                log.error("压缩文件出现异常 :" ,exp);
                isfail = true;
                msg = "压缩文件异常:" + exp.getMessage();
            }
            
            dpath = FileUtil.contactPath(zippath, zipname);
            dname = zipname;
            
        } else {
            // 下载文件时, 检查  fileName不空 , 路径为 root + currentPath + fileName 
            
            if (StringUtils.isBlank(fileName)) {
                log.debug("下载文件时, 上送文件名称为空!");
                isfail = true;
                msg ="下载文件时, 上送文件名称为空!";
            } else {
                dpath  = FileUtil.contactPath(this.fileRoot, FileUtil.contactPath(currentPath,  fileName));
                dname = fileName;
            }
        }
        
        log.info("下载文件路径及名称:" + dpath + " " + dname);
        
        if (isfail) {
            log.info("下载失败" + msg);
            return null;
        } 
        
        return this.export(new File(dpath));
        /**
        else {
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + dname);// 设置文件名
            
            File file = new File(dpath);
            
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
                os.close();
                return  ;
            } catch (Exception e) {
                log.error("读取下载文件异常!" , e);
                
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        log.error("" , e);
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        log.error("" , e);
                        e.printStackTrace();
                    }
                }
            }
        }
        **/
    }
    
    public ResponseEntity<FileSystemResource> export(File file) {
        if (file == null) {
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        return ResponseEntity
                .ok()
                .headers(headers)
                .contentLength(file.length())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(new FileSystemResource(file));
    }

下载使用的是 ResponseEntity<FileSystemResource> , 若使用方法中注释的部分, 直接写response, 可能会报异常 : 写流已打开.

UT010006: Cannot call getWriter(), getOutputStream() already called

文件夹压缩

代码:

    /**
     * 压缩当前目录path下的所有文件 , 生成文件名称为 zipname , 放在路径zippath下 ; 
     * 有异常则抛出 ;
     * @param path
     * @param zippath
     * @param zipname
     * @throws IOException 
     */
    public static void folder2zip(String path, String zippath, String zipname) {
        File src = new File(path);
        ZipOutputStream zos = null;
        
        
        if (src == null  || !src.exists() || !src.isDirectory()) {
            // 源目录不存在 或不是目录 , 则异常  
            logger.error("压缩源目录不存在或非目录!" + path);
            throw new RuntimeException("压缩源目录不存在或非目录!" + path);
        }
        
        File destdir = new File(zippath);
        
        if (!destdir.exists()) {
            // 创建目录  
            logger.info("压缩目标路径不存在, 创建之." + zippath);
            destdir.mkdirs();
        }
        
        File zipfile = new File(contactPath(zippath, zipname));
        
        
        File[] srclist = src.listFiles();
        
        if (srclist == null || srclist.length == 0) {
            // 源目录内容为空,无需压缩 
            logger.error("源目录内容为空,无需压缩下载!" + path);
            throw new RuntimeException("源目录内容为空,无需压缩下载!" + path);
        }
        
        try {
            zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipfile)));
            
            // 递归压缩目录下所有的文件  ;
            compress(zos, src, src.getName());
            
            zos.close();
            
        } catch (FileNotFoundException e) {
            logger.error("压缩文件不存在", e);
            throw new RuntimeException("压缩目标文件不存在!" + e.getMessage());
        } catch (IOException e) {
            logger.error("压缩文件IO异常", e);
            throw new RuntimeException("压缩文件IO异常!" + e.getMessage());
        } 
        finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (Exception e2) {
                    // TODO: handle exception
                }
            }
        }
        
    }
    
    /**
     * 递归压缩文件 
     * @param zos
     * @param src
     * @throws IOException 
     */
    private static void compress(ZipOutputStream zos, File src, String name) throws IOException {
        if (src == null || !src.exists()) {
            return ;
        } 
        if (src.isFile()) {
            byte[] bufs = new byte[10240];
            
            ZipEntry zentry = new ZipEntry(name);
            zos.putNextEntry(zentry);
            
            logger.debug("压缩:" + src.getAbsolutePath());
            FileInputStream in = new FileInputStream(src);
            
            BufferedInputStream bin = new BufferedInputStream(in, 10240);
            
            int readcount = 0 ; 
            
            while( (readcount = bin.read(bufs, 0 , 10240)) != -1) {
                zos.write(bufs, 0 , readcount);
            }
            
            zos.closeEntry();
            bin.close();
        } else {
            // 文件夹  
            File[] fs = src.listFiles();
            
            if (fs == null || fs.length == 0 ) {
                zos.putNextEntry(new ZipEntry(name + File.separator ));
                zos.closeEntry();
                return ;
            }
            
            for (File f : fs) {
                compress(zos, f, name + File.separator + f.getName());
            }
        }
    }

注意: 如何保留原压缩目录的结构 .

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容