2016-04-15 7 views
9

Die aktuelle Architektur meiner Anwendung ermöglicht es mir nicht, eine Datei auf der Serverseite zu speichern und den Link zu dieser gespeicherten Datei zu erstellen. Gibt es andere Optionen (oder ein Code-Snippet), um die Zip-Datei direkt zu streamen und auf der Client-Seite zu speichern?Kann ich ZipFile direkt in Vaadin streamen?

Bearbeiten: Ich denke, meine Frage wurde fehlinterpretiert. Ich bekomme Antworten von Zippen der Dateien und speichern Sie es auf der Clientseite. Das habe ich schon erreicht. Im Folgenden ist das Hauptanliegen der Use-Case-Beispiel:

Szenario: Benutzer rund 5000 Datensätze (ca. Größe von je 1 MB) erhalten hat und Benutzer die untergeordneten Datensätze herunterladen möchten (im CSV-Format) von jedem 5000 Datensätze im ZIP-Format komprimiert. Alle CSV-Dateien werden im laufenden Betrieb generiert.

Ansatz: Da die Größe der ZIP-Datei kann bis zu 5 GB groß sein, so habe ich den Ansatz der direkten Streaming den Inhalt von Dateien in der ZIP-Datei auf der Client-Seite erstellt. Ich habe PipeInputStream und PipeOutputStream dafür verwendet.

Ergebnis: Wie ich bin neu in Vaadin ich in den obigen Ansatz nicht erfolgreich bin so für alle Anregungen/Code-Snippets suchen, die eine direkte Streamen von ZIP-Datei unterstützt auf der Client-Seite (was auch immer die Größe sein kann).

Ich denke, ich bin jetzt klar.

+1

auf den Link: https://vaadin.com/forum#!/ thread/2824570 können Sie eine Diskussion zu diesem Thema finden. –

+0

Unterstützt [dies] (https://vaadin.com/docs/-/part/framework/application/application-resources.html#application.resources.stream) in Verbindung mit [ZipOutputStream] (http: // www. mkyong.com/java/how-to-compress-files-in-zip-format/)? –

+0

@DraganRadevic Vielen Dank für die Freigabe des Links Ich habe diesen Link bereits erkundet, aber die Lösung besagt, dass ich die Datei irgendwo auf meinem Server speichern und den Link erstellen muss, damit der Benutzer diesen Link herunterladen kann. – Milesh

Antwort

2

Die Java-JDK und Apache Commons-Compress lassen Sie ZIP-Archive nicht träge streamen, also habe ich eine Java-ZIP-Bibliothek [1] implementiert, um das zu handhaben. Die aktuelle Einschränkung ist, dass ZIP64-Erweiterungen nicht unterstützt werden, dh Dateien, die größer als 4 GiB sind, können nicht komprimiert werden und es können keine Archive mit mehr als 4 GiB erstellt werden. Ich arbeite daran.

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

1

Sie müssen kein ZIP-Paket erstellen, um eine einzelne Datei über HTTP zu komprimieren. Alle anständigen Browser unterstützen das Lesen komprimierte HTTP-Antwort [1], so lassen wir das nutzen:

@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 { 
    } 
} 

Der Browser des komprimierten Stream herunterzuladen, aber die ursprüngliche Datei speichern, on the fly dekomprimiert.

Pros: das ist sehr speicher-effizient.

Nachteile: Sie können nicht mehrere Dateien in einem einzigen ZIP-Archiv kombinieren.

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

+0

Danke für die Antwort. Aber ich denke, obige Funktion funktioniert, wenn es eine Datei gibt, hier habe ich mehrere Dateien. – Milesh

2

Ihre Frage ist nicht klar. Geben Sie immer etwas von Ihrer Forschung, während Sie eine Frage stellen. Nun, Frage ist von wo Sie einige URL, Fileshare, Datenbank streamen möchten. Welche Vaadin-Version verwenden Sie 6 < oder> 6?

Bearbeitet Es gibt zwei Teile des Problems.

  1. Download Zip-Datei von der Website direkt. Im Folgenden finden Sie ein Beispielcode-Snippet zum Herunterladen der beliebigen Datei.

    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. Huge CSVs Dateien Zippen und downloaden

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

Zipping und in Server-Seite zu speichern ist einfach. Ich denke nicht, dass es aufgrund von Zugriffsproblemen einfacher sein wird, direkt auf die Festplatte des Clients zu speichern (es ist möglich, OutputStream zu verwenden). Sie können es auf Serverseite zippen und den Link zum Client der gezippten Datei freigeben (Datei muss im WebApp-Ordner gespeichert werden).

Sie könnten auch Ausgabestrom nach dem Zippen verwenden, um es herunterzuladen. Unten ist ein einfaches Beispiel dafür.

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

Frage bearbeiten, aktuelle Szenario geben: dann wird es einfach sein, Code-Schnipsel

einige nützliche Links Sie sind unten beziehen zu teilen:

  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. Very large zip file (> 50GB) --> ZipException: invalid CEN header
  4. Java multithreaded file downloading performance
  5. In Java: How to zip file from byte[] array?
  6. Uncompressing a ZIP file in memory in Java
  7. Best way to detect if a stream is zipped in Java
+0

Danke für die Antwort. Ich entschuldige mich dafür, dass ich nicht klar über meine Frage gesprochen habe. Bitte beachten Sie, dass ich die csv-Dateien erfolgreich erstellt, sie gezippt und heruntergeladen habe, ABER das Problem betrifft die Größe der Datei, die 5 GB betragen kann. Gemäß den Geschäftsanforderungen muss ich mehrere CSV-Dateien erstellen, hineinzocken und die ZIP-Datei herunterladen. Die gesamte Aktivität sollte in einer Sitzung abgedeckt werden. Ein Anwendungsfall sind 5000 CSV-Dateien und die Größe jeder Datei kann 1 MB betragen und kann zunehmen, wenn das Feature in Produktion geht. Hoffe das hilft. – Milesh

0

Es ist wie apache.commons.compress sieht ZipArchiveOutputStream ist die Antwort auf Ihre Frage. Aber Sie sollten wissen, dass es eine Reihe von Einschränkungen für Ihre Situation gibt (keine RandomAccessFile). Einfache Probe (Verwendung stdout Umleitung: 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(); 
    } 
} 
2

Ich kann sehen, dass die Antwort vom System automatisch (nicht von mir) angenommen wurde, wie es war 3-mal gewählt. Ich habe damit kein Problem, aber ich möchte die Leute nicht verwirren, die (hier) auf der Suche nach Antworten landen. Ich schätze die Antwort von @ Pratyush Kumar Singh gegeben (wie es Ihnen hilft, mehr zu erkunden) aber leider StackOverFlowIch kann die Antwort nicht akzeptieren, da meine Frage noch nicht beantwortet wurde. Ich arbeite immer noch daran und werde die Antwort veröffentlichen, sobald ich durch POC gelöst habe.

+1

Hallo @Milesh, nach dem Graben mehr um Ihr Problem Ich fand heraus, dass Ihr Problem ist, dass im Grunde alle Java-ZIP-Implementierungen auf dem Markt nur Push-Stil-API (unbedingt zu temporären OutputStream schreiben, dann in InputStream konvertieren). Ihr Problem kann mit einer Pull-Stil-API im Sinne von SequenceInputStream gelöst werden, aber ich konnte eine solche Implementierung nicht finden. Ich denke daran, es selbst zu implementieren :) – Tair

+0

@tair Genau das stimme ich dir zu. Bitte teilen Sie mit mir, wenn Sie etwas gefunden haben funktioniert :) – Milesh

+0

hey @Milesh endlich habe ich es! Schau in meine zweite Antwort! – Tair