我尝试从2个文件创建zip时出错

问题描述

我正在尝试将2个文件合并到一个zip文件中

myMainMethod

private void downloadFileByTypeInner(StaticDocument file,String productCode,int productVersion) throws IOException,TechnicalException {
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    HttpServletResponse response = (HttpServletResponse) ec.getResponse();
    String distrib = MultinetFrontHelper.getDefaultDitrib();
    String realPath = findRealPath(ec,file.getPath().replace("{DISTRIB}",distrib));
    String downloadName = file.getDownloadFileName() != null ? file.getDownloadFileName() : file.getPath();

    if (file.getAction() == null || file.getAction().trim().isEmpty() || file.getAction().equals("download")) {
        List<java.io.File> l = new ArrayList<>();
        java.io.File f = new java.io.File(realPath);
        l.add(f);
        if(file.getDependOnCodeFiles() != null){
            String[] paths  = file.getDependOnCodeFiles().split(",");
            for (String codefile : paths) {

                StaticDocument file2 = libraryBusinessService.getFileByCodeType(codefile,productCode,productVersion);
                if((file2 != null)) {
                    l.add(new java.io.File(findRealPath(ec,file2.getPath())));
                }
            }
            downloadName = downloadName.substring(0,downloadName.lastIndexOf("."))+".zip";
        }
        InputStream pathStream = DownLoadHelper.getStreamAllFiles(l.toArray(new java.io.File[0]),downloadName);

        if (pathStream != null) {
            if(downloadName.indexOf('/')!=-1) {
                downloadName = downloadName.substring(downloadName.lastIndexOf('/')+1);
            }
            DownLoadHelper.downLoadFile(response,pathStream,downloadName);
        } else {
            logger.error("Le fichier " + realPath + " est introuvable!");
            throw new TechnicalException(CodeError.CODE_ERTEMO0001,null);
        }

    } else if (file.getAction().equals("open")) {
        final FacesContext ctx = FacesContext.getCurrentInstance();
        final ExternalContext extContext = ctx.getExternalContext();
        try {
            extContext.redirect(file.getPath());
        } catch (final IOException ioe) {
            throw new FacesException(ioe);

        }
    }
}

getStreamAllFiles

public static InputStream getStreamAllFiles(final File[] listDoc,String nameZIP) throws IOException {
    InputStream stream = null;
    if (listDoc != null) {
        if (listDoc.length == 1) {
            stream = new  ByteArrayInputStream(FileUtils.readFileToByteArray(listDoc[0]));
        } else if (listDoc.length > 1) {
            try( ByteArrayOutputStream baos = new ByteArrayOutputStream();ZipOutputStream zos = new ZipOutputStream(baos)){

                for (int i = 0; i < listDoc.length; i++) {

                    try(InputStream fis = new  ByteArrayInputStream(FileUtils.readFileToByteArray(listDoc[i]));BufferedInputStream bis = new BufferedInputStream(fis)){
                        zos.putNextEntry(new ZipEntry(listDoc[i].getName()));
                        byte[] bytes = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = bis.read(bytes)) != -1) {
                            zos.write(bytes,bytesRead);
                        }
                    }
                }

                zos.closeEntry();

                stream = new ByteArrayInputStream(baos.toByteArray());
            }
        }
    }
    return stream;
}

下载文件

public static void downLoadFile(HttpServletResponse response,InputStream pathStream,String fileName) throws IOException {
    response.setContentType("application/octet-stream");
    response.setHeader("Content-Disposition","attachment;filename=" + fileName);


    ServletOutputStream out = response.getOutputStream();
    IOUtils.copyLarge(pathStream,out);
    out.flush();
    FacesContext.getCurrentInstance().responseComplete();
    IOUtils.closeQuietly(pathStream);
    IOUtils.closeQuietly(out);

}

尝试打开zip文件时出现此错误

enter image description here

解决方法

我想您正在尝试使用多个文件制作一个zip文件。问题出在您的getStreamAllFiles方法中,因为您没有在放置文件内容后关闭zip条目,也没有关闭ZipOutputStream和循环的结尾,因此文件循环应如下所示:

for (int i = 0; i < listDoc.length; i++) {

    try(InputStream fis = new  ByteArrayInputStream(FileUtils.readFileToByteArray(listDoc[i]));BufferedInputStream bis = new BufferedInputStream(fis)){
        zos.putNextEntry(new ZipEntry(listDoc[i].getName()));
        byte[] bytes = new byte[1024];
        int bytesRead;
        while ((bytesRead = bis.read(bytes)) != -1) {
            zos.write(bytes,bytesRead);
        }
        zos.closeEntry();
    }
}
zos.close();
stream = new ByteArrayInputStream(baos.toByteArray());

即在文件中循环移动zos.closeEntry()

如果不将其移动到listDoc.length循环中,则如果有多个文件,则在每个条目的末尾将无法正确关闭ZipEntry。您还需要在ZipOutputStream上发出一个close(),否则它将不会写入zip结束目录(如果在命令行工具下测试该文件,则会显示为错误End-of-central-directory signature not found

此外,我将字节缓冲区的分配移到文件循环的外部 ,因为您只需要分配一次,然后对正在编写的所有文件重复使用相同的缓冲区。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...