springrest-create.zip文件并将其发送到客户端

3mpgtkmj  于 2021-06-30  发布在  Java
关注(0)|答案(4)|浏览(375)

我想创建一个.zip文件,其中包含我从后端接收的压缩文件,然后将此文件发送给用户。两天来我一直在寻找答案,却找不到合适的解决办法,也许你能帮我:)
现在,代码是这样的:(我知道我不应该在spring控制器中做所有的事情,但是不关心这个,它只是为了测试的目的,为了找到让它工作的方法)

@RequestMapping(value = "/zip")
    public byte[] zipFiles(HttpServletResponse response) throws IOException{
        //setting headers
        response.setContentType("application/zip");
        response.setStatus(HttpServletResponse.SC_OK);
        response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");

        //creating byteArray stream, make it bufforable and passing this buffor to ZipOutputStream
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream);
        ZipOutputStream zipOutputStream = new ZipOutputStream(bufferedOutputStream);

        //simple file list, just for tests
        ArrayList<File> files = new ArrayList<>(2);
        files.add(new File("README.md"));

        //packing files
        for (File file : files) {
            //new zip entry and copying inputstream with file to zipOutputStream, after all closing streams
            zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
            FileInputStream fileInputStream = new FileInputStream(file);

            IOUtils.copy(fileInputStream, zipOutputStream);

            fileInputStream.close();
            zipOutputStream.closeEntry();
        }

        if (zipOutputStream != null) {
            zipOutputStream.finish();
            zipOutputStream.flush();
            IOUtils.closeQuietly(zipOutputStream);
        }
        IOUtils.closeQuietly(bufferedOutputStream);
        IOUtils.closeQuietly(byteArrayOutputStream);
        return byteArrayOutputStream.toByteArray();
    }

但问题是,使用代码,当我输入url时:localhost:8080/zip 我得到文件:test.zip.html而不是.zip文件

当我删除.html扩展名并只保留test.zip时,它会正确打开,如何避免返回这个.html扩展名?为什么要加?

我不知道还能做什么。我还尝试用tearrayouputstream替换如下内容:

OutputStream outputStream = response.getOutputStream();

并将该方法设置为void,使其不返回任何内容,但它创建了.zip文件,该文件是。。损坏?
在打开test.zip后,我在macbook上看到test.zip.cpgz,它又给了我test.zip文件等等。。
在windows上,我说的.zip文件已经损坏,甚至无法打开。
我还认为,自动删除.html扩展将是最好的选择,但是如何删除呢?希望没有看起来那么难:)谢谢

13z8s7eq

13z8s7eq1#

似乎已经解决了。我替换了:

response.setContentType("application/zip");

使用:

@RequestMapping(value = "/zip", produces="application/zip")

现在我明白了,漂亮的.zip文件:)
如果你们中有谁有更好或更快的建议,或者只是想给出一些建议,那就去吧,我很好奇。

svdrlsy4

svdrlsy42#

我正在使用 REST Web ServiceSpring Boot 我设计的端点总是返回 ResponseEntity 不管是不是 JSON 或者 PDF 或者 ZIP 我提出了下面的解决方案,部分是受 denov's answer 在这个问题以及另一个问题,我学会了如何转换 ZipOutputStream 进入 byte[] 为了把它喂给 ResponseEntity 作为端点的输出。
总之,我创建了一个简单的实用程序类,其中有两个 pdf 以及 zip 文件下载

@Component
public class FileUtil {
    public BinaryOutputWrapper prepDownloadAsPDF(String filename) throws IOException {
        Path fileLocation = Paths.get(filename);
        byte[] data = Files.readAllBytes(fileLocation);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/pdf"));
        String outputFilename = "output.pdf";
        headers.setContentDispositionFormData(outputFilename, outputFilename);
        headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");

        return new BinaryOutputWrapper(data, headers); 
    }

    public BinaryOutputWrapper prepDownloadAsZIP(List<String> filenames) throws IOException {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("application/zip"));
        String outputFilename = "output.zip";
        headers.setContentDispositionFormData(outputFilename, outputFilename);
        headers.setCacheControl("must-revalidate, post-check=0, pre-check=0");

        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
        ZipOutputStream zipOutputStream = new ZipOutputStream(byteOutputStream);

        for(String filename: filenames) {
            File file = new File(filename); 
            zipOutputStream.putNextEntry(new ZipEntry(filename));           
            FileInputStream fileInputStream = new FileInputStream(file);
            IOUtils.copy(fileInputStream, zipOutputStream);
            fileInputStream.close();
            zipOutputStream.closeEntry();
        }           
        zipOutputStream.close();
        return new BinaryOutputWrapper(byteOutputStream.toByteArray(), headers); 
    }
}

现在端点可以很容易地返回 ResponseEntity<?> 如下所示使用 byte[] 专门为 pdf 或者 zip .

@GetMapping("/somepath/pdf")
public ResponseEntity<?> generatePDF() {
    BinaryOutputWrapper output = new BinaryOutputWrapper(); 
    try {
        String inputFile = "sample.pdf"; 
        output = fileUtil.prepDownloadAsPDF(inputFile);
        //or invoke prepDownloadAsZIP(...) with a list of filenames
    } catch (IOException e) {
        e.printStackTrace();
        //Do something when exception is thrown
    } 
    return new ResponseEntity<>(output.getData(), output.getHeaders(), HttpStatus.OK); 
}

这个 BinaryOutputWrapper 是简单不变的 POJO 我创建的类 private byte[] data; 以及 org.springframework.http.HttpHeaders headers; 作为字段以返回 data 以及 headers 从实用方法。

uplii1fm

uplii1fm3#

@RequestMapping(value="/zip", produces="application/zip")
public void zipFiles(HttpServletResponse response) throws IOException {

    //setting headers  
    response.setStatus(HttpServletResponse.SC_OK);
    response.addHeader("Content-Disposition", "attachment; filename=\"test.zip\"");

    ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());

    // create a list to add files to be zipped
    ArrayList<File> files = new ArrayList<>(2);
    files.add(new File("README.md"));

    // package files
    for (File file : files) {
        //new zip entry and copying inputstream with file to zipOutputStream, after all closing streams
        zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
        FileInputStream fileInputStream = new FileInputStream(file);

        IOUtils.copy(fileInputStream, zipOutputStream);

        fileInputStream.close();
        zipOutputStream.closeEntry();
    }    

    zipOutputStream.close();
}
6gpjuf90

6gpjuf904#

@RequestMapping(value="/zip", produces="application/zip")
public ResponseEntity<StreamingResponseBody> zipFiles() {
    return ResponseEntity
            .ok()
            .header("Content-Disposition", "attachment; filename=\"test.zip\"")
            .body(out -> {
                var zipOutputStream = new ZipOutputStream(out);

                // create a list to add files to be zipped
                ArrayList<File> files = new ArrayList<>(2);
                files.add(new File("README.md"));

                // package files
                for (File file : files) {
                    //new zip entry and copying inputstream with file to zipOutputStream, after all closing streams
                    zipOutputStream.putNextEntry(new ZipEntry(file.getName()));
                    FileInputStream fileInputStream = new FileInputStream(file);

                    IOUtils.copy(fileInputStream, zipOutputStream);

                    fileInputStream.close();
                    zipOutputStream.closeEntry();
                }

                zipOutputStream.close();
            });
}

相关问题