有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java我可以在vaadin中直接流式处理ZipFile吗?

我的应用程序的当前架构不允许我在服务器端存储文件并创建指向该存储文件的链接。那么,是否有其他选项(或代码片段)可以直接流式处理ZipFile并将其存储在客户端

编辑: 我想我的问题被误解了。我收到了压缩文件并将其存储在客户端的答案。我已经做到了。下面是示例用例的主要关注点:

场景: 用户有大约5000条记录(每个大约1 MB大小),用户希望下载压缩为ZIP格式的每5000条记录的子记录(CSV格式)。所有CSV文件都是动态生成的

方法: 由于ZIP文件的大小可以达到5gb,所以我采用了直接将文件内容流式传输到客户端创建的ZIP文件的方法。为此,我使用了PipeInputStream和PipeOutputStream

结果: 由于我是vaadin的新手,我在上述方法中并不成功,因此我正在寻找任何支持将ZIP文件(无论大小)直接流式传输到客户端的建议/代码片段

我想我现在明白了


共 (5) 个答案

  1. # 1 楼答案

    JavaJDK和ApacheCommons压缩不允许惰性地流式传输ZIP存档,因此我实现了一个JavaZIP库[1]来处理这个问题。当前的限制是它不支持ZIP64扩展,这意味着它不能压缩大于4 GiB的文件,也不能生成大于4 GiB的档案。我正在努力

    [1]https://github.com/tsabirgaliev/zip

  2. # 2 楼答案

    我可以看到答案已经被系统自动接受(不是我),因为它被投票了3次。我对此没有异议,但我不想混淆那些(以防万一)降落在这里寻找答案的人。我感谢@Pratyush Kumar Singh给出的答案(因为这有助于您进行更多探索),但很抱歉,StackOverFlow我无法接受答案,因为我的问题尚未得到回答。我仍在努力,并将张贴的答案,一旦我通过POC解决

  3. # 3 楼答案

    通过HTTP压缩单个文件不必创建ZIP包。所有体面的浏览器都支持读取压缩的HTTP响应[1],因此让我们利用这一点:

    @Theme("mytheme")
    @Widgetset("org.test.MyAppWidgetset")
    public class MyUI extends UI {
    
        @Override
        protected void init(VaadinRequest vaadinRequest) {
            Button downloadButton = new Button("Download File");
    
            StreamResource myResource = createResource();
            FileDownloader fileDownloader = new FileDownloader(myResource);
            fileDownloader.extend(downloadButton);
    
            setContent(downloadButton);
        }
    
        private StreamResource createResource() {
            return new StreamResource(new StreamResource.StreamSource() {
                @Override
                public InputStream getStream() {
                    InputStream s = null;
                    try {
                        s = new DeflaterInputStream(new FileInputStream("/tmp/some.csv"));
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                    return s;
    
                }
            }, "some.csv") {
                @Override
                public DownloadStream getStream() {
                    DownloadStream ds =  super.getStream();
                    ds.setParameter("Content-Encoding", "deflate");
                    return ds;
                }
            };
        }
    
        @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
        @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
        public static class MyUIServlet extends VaadinServlet {
        }
    }
    

    浏览器将下载压缩的流,但保存原始文件,动态解压缩

    优点:这非常节省内存

    缺点:不能将多个文件合并到一个ZIP存档中

    [1]https://en.wikipedia.org/wiki/HTTP_compression

  4. # 4 楼答案

    它看起来像阿帕奇。平民压缩ZipArchiveOutputStream是您问题的答案。但是您应该知道,您的情况有一系列限制(没有随机访问文件)。简单示例(使用stdout重定向:java-cp-Test>;Test.zip):

    import org.apache.commons.compress.archivers.ArchiveEntry;
    import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
    import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
    import java.util.Arrays;
    
    public class Test {
    
    public static void main(String[] args) throws Exception {
          ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(System.out);
          byte[] data = new byte[1024*1024];
          for(byte i=49; i<120; i++) {
              Arrays.fill(data, i);
              ArchiveEntry file1 = new ZipArchiveEntry("file" + i + ".txt");
              zipOut.putArchiveEntry(file1);
              zipOut.write(data);
              zipOut.closeArchiveEntry();
           }
           zipOut.finish();
           zipOut.close();
        }
    }
    
  5. # 5 楼答案

    你的问题不清楚。在发布问题时,一定要做一些调查。现在,问题是您想从哪里流式传输一些URL、文件共享和数据库。您使用的是什么Vaadin版本6<;或>;6?

    编辑问题分为两部分

    1. 直接从网站下载Zip文件。下面是下载任意文件的示例代码段

      import java.io.BufferedInputStream;
      import java.io.ByteArrayInputStream;
      import java.io.ByteArrayOutputStream;
      import java.io.InputStream;
      import java.net.URL;
      
      import javax.servlet.annotation.WebServlet;
      
      import com.vaadin.annotations.Theme;
      import com.vaadin.annotations.VaadinServletConfiguration;
      import com.vaadin.server.FileDownloader;
      import com.vaadin.server.StreamResource;
      import com.vaadin.server.StreamResource.StreamSource;
      import com.vaadin.server.VaadinRequest;
      import com.vaadin.server.VaadinServlet;
      import com.vaadin.ui.Button;
      import com.vaadin.ui.UI;
      
      @SuppressWarnings("serial")
      @Theme("vaadintest")
      public class VaadintestUI extends UI {
      
          @WebServlet(value = "/*", asyncSupported = true)
          @VaadinServletConfiguration(productionMode = false, ui = VaadintestUI.class)
          public static class Servlet extends VaadinServlet {
          }
      
          protected void init(VaadinRequest request) {
              Button downloadButton = new Button("Download Zip File");
      
              StreamResource myResource = createResource();
              FileDownloader fileDownloader = new FileDownloader(myResource);
              fileDownloader.extend(downloadButton);
      
              setContent(downloadButton);
          }
      
      private StreamResource createResource() {
          return new StreamResource(new StreamSource() {
              @Override
              public InputStream getStream() {
      
                  BufferedInputStream in = null;
                  ByteArrayOutputStream bao = null;
                  try {
                      in = new BufferedInputStream(
                              new URL("http://www-us.apache.org/dist/commons/io/binaries/commons-io-2.5-bin.zip" + "")
                                      .openStream());
                      byte[] buff = new byte[8000];
                      int bytesRead = 0;
                      bao = new ByteArrayOutputStream();
      
                      while ((bytesRead = in.read(buff)) != -1) {
                          bao.write(buff, 0, bytesRead);
                      }
      
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return new ByteArrayInputStream(bao.toByteArray());
      
              }
          }, "somefile.zip");
      }
      

      }

    2. 压缩巨大的CSV文件并下载

    参考:Best Practices to Create and Download a huge ZIP (from several BLOBs) in a WebApp

    压缩和存储在服务器端很容易。由于访问问题,我认为直接存储到客户机磁盘并不容易(可以使用OutputStream)。您可以在服务器端压缩它,并共享到压缩文件客户端的链接(文件需要存储在WebApp文件夹中)

    此外,您还可以在压缩后使用输出流下载它。下面是一个简单的例子

    参考:http://www.mkyong.com/java/how-to-download-file-from-website-java-jsp/

    编辑问题,给出实际场景:这样就很容易共享代码片段了

    您可以参考以下一些有用的链接:

    1. Best Practices to Create and Download a huge ZIP (from several BLOBs) in a WebApp
    2. How to split a huge zip file into multiple volumes?
    3. Zip files with Java: Is there a limit?
    4. Very large zip file (> 50GB) --> ZipException: invalid CEN header
    5. Java multithreaded file downloading performance
    6. In Java: How to zip file from byte[] array?
    7. Uncompressing a ZIP file in memory in Java
    8. Best way to detect if a stream is zipped in Java