tutorials.de Buch-Aktion 05/2012
Seite 1 von 2 12 LetzteLetzte
ERLEDIGT
JA
ANTWORTEN
15
ZUGRIFFE
4423
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Avatar von Gainwar
    Gainwar Gainwar ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Ort
    Augsburg
    Beiträge
    128
    Hi,

    bin zur Zeit dran eine Weboberfläche für Subversion zu programmieren. (Wie ViewCVS). Ich arbeite hierzu mit der aktuellen "svn-javahl-1.3", welche die neue Methode streamFileContent(...) zur Verfügung stellt.

    Nun, wenn ein User auf ein File klickt bekommt er zusätzlich die Möglichkeit sich diese Datei herunterzuladen. Diese File soll nicht erst auf dem Server zwischengespeichert werden, sondern direkt an den User geschickt werden. An sich ja kein Problem, funktioniert auch gut. Das Problem ensteht erst wenn die Datei eine etwas höhere Größe hat, z.B. 80 MB und größer. Ganz klar eigentlich, den schließlich speichere ich die Datei in einem byte[] welche ich dann über ein Servlet an den User schicke. Hier ein bisschen Code meines Download Servlets:

    PHP-Code:
        public void doPost(HttpServletRequest requestHttpServletResponse response)
                
    throws ServletExceptionIOException {
            
            
    // Get request and params.
            //String filename = request.getPathInfo();
            
    long revision Long.parseLong(request.getParameter("revision"));
            
    String path        request.getParameter("path");
            
    String filename request.getParameter("filename");
            
            
    // Set content type. (force download)
            
    response.setContentType("application/octet-stream");
            
    response.setHeader("Content-Disposition""attachment; filename=" filename ";");
            
    //response.setHeader("Content-Length","...");

            // Get the output stream.
            
    ServletOutputStream out response.getOutputStream();
            
            
    // Get current instance of FacesContext and Application.
            
    FacesContext fc FacesContext.getCurrentInstance();
            
    Application    app fc.getApplication();
            
            
    // Get controller and connector.
            
    ControllerBean controller = (ControllerBean)app.createValueBinding("#{Controller}").getValue(fc);
            
    SVNConnector svn_connector = (SVNConnector)controller.getConnector();
            
            
    // Subversion repository url.
            
    String strRepos svn_connector.getRepository();
            
            
    // File content.
            
    byte[] content svn_connector.getFileContentstrRepos pathRevision.getInstance(revision));
            
            
    // Initialize download.
            
    out.writecontent );
            
    out.flush();
            
    out.close();

        } 
    Eigentlich liegt der Fehler auf der Hand, die Zwischenspeicherung im byte[] verursacht den Heap overflow. Falsch, der Fehler passiert bereits in der von der svn-javahl gegebenen Methode "streamFileContent", welche mir meinen übergebenen OutputStream füllt. Habe mir auch den native Code angesehen. Das Problem ist die Methode füllt den Stream komplett, womit ich keine Chance habe eine Bufferung vorzunehmen. Hier der native Codeteil welcher den Stream füllt:

    PHP-Code:
       while (contentSize 0)
       {
           
    size_t readSize bufSize contentSize contentSize bufSize;
           
    Err svn_stream_read(read_stream, (char *)bufData, &readSize);
           if (
    Err != NULL)
           {
               
    env->ReleaseByteArrayElements(bufferbufData0);
               
    svn_stream_close(read_stream);
               
    JNIUtil::handleSVNError(Err);
               return;
           }

           
    env->ReleaseByteArrayElements(bufferbufDataJNI_COMMIT);
           
    env->CallVoidMethod(outputStreamwriteMethodbuffer0readSize);
           if (
    JNIUtil::isJavaExceptionThrown())
           {
               
    env->ReleaseByteArrayElements(bufferbufData0);
               
    svn_stream_close(read_stream);
               return;
           }
           
    contentSize -= readSize;
       } 
    Nun wäre meine Frage, wie kann ich den Stream -direkt- an den User zum Download weiterleiten, ohne vorher eine Working copy der File auf dem Server anzulegen.

    Vielen Dank, Gruß
    - Manuel

    PS: Entschuldigung das ich PHP-Code boxen genommen habe, aber da dies die einzigen sind welche ein Highlight benutzen, nahm ich diese damit ihr den Code besser lesen könnt.
     
    Manuel Freiholz
    iF.Gainwar

    iF.SVNAdmin (http://www.insanefactory.com/if-svnadmin/)
    Subversion Benutzeradministration mit PASSWD und LDAP Integration.

  2. #2
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo!

    Wie man eine Datei zu einem Client streamen kann findest du hier:
    http://www.tutorials.de/forum/java/2...light=Download

    Die SVNConnector Klasse scheint eine Eigenenentwicklung von dir zu sein, bzw. kann ich diese nicht im javah SVN Verzeichnis finden:
    http://svn.collab.net/viewcvs/svn/tr...ersion/javahl/
    Schaut man sich das SVNClientInterface - Interface an: http://svn.collab.net/viewcvs/svn/tr...60&view=markup
    So findet man die von dir genannte Methode:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
       /**
         * Write the file's content to the specified output stream.  If
         * you need an InputStream, use a
         * PipedInputStream/PipedOutputStream combination.
         *
         * @param path        the path of the file
         * @param revision    the revision to retrieve
         * @param pegRevision the revision at which to interpret the path
         * @param the stream to write the file's content to
         * @throws ClientException
         * @see <a href="[URL="http://java.sun.com/j2se/1.4.2/docs/api/java/io/PipedOutputStream.html"]http://java.sun.com/j2se/1.4.2/docs/api/java/io/PipedOutputStream.html[/URL]">PipedOutputStream</a>
         * @see <a href="[URL="http://java.sun.com/j2se/1.4.2/docs/api/java/io/PipedInputStream.html"]http://java.sun.com/j2se/1.4.2/docs/api/java/io/PipedInputStream.html[/URL]">PipedInputStream</a>
         */
        void streamFileContent(String path, Revision revision, Revision pegRevision,
                               int bufferSize, OutputStream stream) 
            throws ClientException;
    In deinem geposteten Codeschnippsel kann ich den Aufruf dieser Methode leider nicht entdecken. (Hast du die vielleicht am SVNConnector implementiert?) Vielleicht solltest du diese Methode einfach mal direkt verwenden via SVNClient.

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  3. #3
    Avatar von Gainwar
    Gainwar Gainwar ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Ort
    Augsburg
    Beiträge
    128
    Hi,

    die Methode "streamFileContent" rufe ich über meine "getFileContent" auf:

    PHP-Code:
        public byte[] getFileContent(String pathRevision rev){

            
    ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                
    client.streamFileContent(pathrevrev256out);
            } catch (
    ClientException e) {
                
    jlog.error("Can't get file content from subversion.");
                
    e.printStackTrace();
            }
            
    // TODO: The content should NOT be saved in a variable.
            // TODO: The return type should be void or a stream.
            // TODO: Big files would cause an java heap space exception.
            
    byte[] content out.toByteArray();
            return 
    content;
        } 
    --> client = SVNClient();

    So läuft es im Moment. ( nur mit kleinen Files )
    Hatte es auch schon mit PipedOutput/Input -Streams, allerdings helfen diese auch nichts, weil die Methode "streamFileContent" den overflow verursacht. Auch Threads scheinen in diesem Fall nichts zu bringen da ich nicht in den Prozess der native File eingreifen kann. Alles schon versucht

    Gruß
    - Manuel
     
    Manuel Freiholz
    iF.Gainwar

    iF.SVNAdmin (http://www.insanefactory.com/if-svnadmin/)
    Subversion Benutzeradministration mit PASSWD und LDAP Integration.

  4. #4
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo!

    Gibts vom eurem Projekt schon ne Lauffaehige Version? Wenn ja wuerde ich heute Abend mal mein Glueck versuchen.

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  5. #5
    Avatar von Gainwar
    Gainwar Gainwar ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Ort
    Augsburg
    Beiträge
    128
    Hi,
    kann dir das Projekt leider nicht schicken - siehe PM.
    Für das Problem hier dennoch weiter, evtl. weis jemand anders bescheid oder man kann jemanden helfen.

    In deinem Tutorial hast du alles ja schön beschrieben, das Problem ist nur dass ich durch Subversion keine reale Datei habe sondern nur einen vollen Stream und somit keinen File Stream erstellen kann. Bin gerade noch dabei ViewCVS Source zu durchstöbern um zu sehen wie diese das Problem gelöst haben.

    Gruß
    - Manuel
     
    Manuel Freiholz
    iF.Gainwar

    iF.SVNAdmin (http://www.insanefactory.com/if-svnadmin/)
    Subversion Benutzeradministration mit PASSWD und LDAP Integration.

  6. #6
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo!

    Hast du es schonmal mit:
    Code :
    1
    2
    3
    4
    5
    
    ServletOutputStream out = response.getOutputStream();
    ...
    streamFileContent(strRepos + path,Revision.getInstance(revision), XXXX,
                               16384, out);
    ...
    versucht?

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  7. #7
    Avatar von Gainwar
    Gainwar Gainwar ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Ort
    Augsburg
    Beiträge
    128
    Hi!

    Jopp, schon versucht und auch schon mit dem response.getWriter().
    Zudem tritt der overflow innerhalb der Methode streamFileContent auf, was bedeutet ich komm nicht weiter um den Stream in irgend einer Art zu Weise zu behandeln.

    Vermute ich brauche einfach eine andere Methode, aber ich schau mich noch um.

    Gruß
    - Manuel
     
    Manuel Freiholz
    iF.Gainwar

    iF.SVNAdmin (http://www.insanefactory.com/if-svnadmin/)
    Subversion Benutzeradministration mit PASSWD und LDAP Integration.

  8. #8
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo!

    Folgendes:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    package de.tutorials;
     
    import java.io.File;
    import java.io.FileOutputStream;
     
    import org.tigris.subversion.javahl.Revision;
    import org.tigris.subversion.javahl.SVNClient;
    import org.tigris.subversion.javahl.SVNClientInterface;
     
    public class SVNRepositoryDownloadExample {
        /**
         * @param args
         */
        public static void main(String[] args) throws Exception{
            SVNClientInterface svnClient = new SVNClient();
            svnClient.username("tom");
            svnClient.password("tom");
            FileOutputStream fileOutputStream = new FileOutputStream(new File("c:/Nordwind.mdb"));
            svnClient.streamFileContent("svn://localhost/de.tutorials.svn/Nordwind.mdb",Revision.getInstance(7L),Revision.getInstance(7L),16384,fileOutputStream);
            fileOutputStream.close();
        }
    }
    ...funktioniert mit einer (künstlich etwas aufgeblähten) 15 MB großen Nordwind.mdb einwandfrei. Ich denke so solltest du auch von einem Servlet aus Streamen können.

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  9. #9
    Avatar von Gainwar
    Gainwar Gainwar ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Ort
    Augsburg
    Beiträge
    128
    Hi,
    leider muss ich dir sagen das diese Möglichkeit auch nicht funktioniert.
    Das Problem liegt einfach an der native Methode in die nicht eingegriffen werden kann.

    Werd noch ein paar andere Möglichkeiten versuchen und bescheid geben wenn ich eine Lösung gefunden habe.

    Gruß Manuel
     
    Manuel Freiholz
    iF.Gainwar

    iF.SVNAdmin (http://www.insanefactory.com/if-svnadmin/)
    Subversion Benutzeradministration mit PASSWD und LDAP Integration.

  10. #10
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo!

    Ich wette das funktioniert genau so wie oben beschrieben... ob ich nun die Datei in ein File streame oder ueber ein Servlet zum Client schicke ist doch egal
    Ich baue heute Abend mal ein Beispiel dazu.
    Ich habe uebrigens die entsprechenden Jars aus dem Subclipse Eclipse-Plugin verwendet.

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  11. #11
    Avatar von Gainwar
    Gainwar Gainwar ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Ort
    Augsburg
    Beiträge
    128
    Hi Tom,
    wir haben uns nun eine andere Lösung einfallen lassen.
    Der Download wird über den Commandline Befehl "svn cat" durchgeführt und somit kann der STDOUT leicht gebuffert werden und an den User weitergeleitet werden. Für Uploads -muss- eine Working Copy vorhanden sein, welche wir somit auch führen werden (temporär).

    Gute Nacht
    - Manuel
     
    Manuel Freiholz
    iF.Gainwar

    iF.SVNAdmin (http://www.insanefactory.com/if-svnadmin/)
    Subversion Benutzeradministration mit PASSWD und LDAP Integration.

  12. #12
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Leider konnte ich mich gestern Abend nicht mehr an den rechner setzen...
    Ich denke immernoch, dass das auch anders moeglich ist. Werde mich am WE mal damit beschaeftigen.

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  13. #13
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo!

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    
    package de.tutorials.web.svn.servlet;
     
    import java.io.IOException;
     
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    import org.tigris.subversion.javahl.ClientException;
    import org.tigris.subversion.javahl.Revision;
    import org.tigris.subversion.javahl.SVNClient;
    import org.tigris.subversion.javahl.SVNClientInterface;
     
    /**
     * Servlet implementation class for Servlet: SVNDownloadServlet
     * 
     * @web.servlet name="SVNDownloadServlet" display-name="SVNDownloadServlet"
     * 
     * @web.servlet-mapping url-pattern="/SVNDownloadServlet"
     * 
     */
    public class SVNDownloadServlet extends javax.servlet.http.HttpServlet
            implements javax.servlet.Servlet {
     
        /*
         * (non-Java-doc)
         * 
         * @see javax.servlet.http.HttpServlet#HttpServlet()
         */
        public SVNDownloadServlet() {
            super();
        }
     
        /*
         * (non-Java-doc)
         * 
         * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request,
         *      HttpServletResponse response)
         */
        protected void doGet(HttpServletRequest request,
                HttpServletResponse response) throws ServletException, IOException {
     
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition",
                    "attachment; filename=eclipse.dat;");
     
            SVNClientInterface svnClient = null;
            try {
                svnClient = new SVNClient();
                svnClient.username("tom");
                svnClient.password("tom");
                svnClient.streamFileContent(
                        "svn://localhost/de.tutorials.web.svn/eclipse.zip",
                        Revision.getInstance(14L), Revision.getInstance(14L),
                        16384, response.getOutputStream());
            } catch (ClientException e) {
                e.printStackTrace();
            } finally {
                if (svnClient != null) {
                    svnClient.dispose();
                }
            }
        }
    }

    Funktioniert bei mir ohne Probleme Im Browser kommt ein "Datei speichern unter" Dialog hoch.
    Ich denke das ist etwas bequemer als den OUTPUT auf der Konsole zu verarbeiten...

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  14. #14
    Avatar von Gainwar
    Gainwar Gainwar ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Ort
    Augsburg
    Beiträge
    128
    Hi Tom,
    bin schon zuhause, aber ich weis das haben wir schon versucht und mit großen Files entstehen dadurch Probleme. Nicht das mich mcih evtl die ganze Zeit falsch verstanden hast, aber mit normalen kleinen txt Files hab ich schon dutzende Varianten zum laufen gebracht. Das Problem ist wenn ich Dateien mit 300 MB oder mehr herunterladen will. Versuch es mal bei dir, wirst sehen das du einen "Java heap space" bekommst.

    Gruß
    - Manuel
     
    Manuel Freiholz
    iF.Gainwar

    iF.SVNAdmin (http://www.insanefactory.com/if-svnadmin/)
    Subversion Benutzeradministration mit PASSWD und LDAP Integration.

  15. #15
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
    Hallo!

    1) Okay das habe ich noch nicht evrsucht... meine groessten Dateien waren 30 MB.
    2) Was haben so grosse binaere Dateien in einem Repository zu suchen?! Das ist in meinen Augen Bloedsinn... die sollte man woanders (ausserhalb des Repositories) ablegen.

    Edit:
    Das Problem scheint ein Memory leak in einer der javahl DLLs zu sein. Bei mir bleibt der Speicherverbrauch im taskmanager bei 17-18 MB (Tomcat Prozess). Schaue ich hingegen unter dem reiter Performance auf den Status der Auslagerungsdatei, so waechst diese alle 30 Sekunden um 15 MB... habs mal mit einem 300 MB grossen Zip File ausprobiert. Scheinbar wird dort der byte[] Puffer nicht mehr freigegeben...
    Im javasvn.jar im subclipse Plugin findet man noch SVNWCClient dieser bietet auch eine Methode doGetFileContents(....) an welche keine Probleme mit grossen Dateien hat. Allerdings wird dazu auf dem Server eine temporaere Datei erstellt welche dann zum Client gestreamt und danach geloescht wird.

    Gruss Tom
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

Ähnliche Themen

  1. Subversion Hosting
    Von eagle1985 im Forum Hosting & Webserver
    Antworten: 6
    Letzter Beitrag: 21.01.11, 22:06
  2. Subversion Konfiguration
    Von caramba12321 im Forum Linux & Unix
    Antworten: 1
    Letzter Beitrag: 05.11.09, 00:18
  3. Subversion
    Von Arndtinho im Forum Coders Talk
    Antworten: 2
    Letzter Beitrag: 03.05.07, 08:51
  4. Subversion Server
    Von ava99 im Forum Hosting & Webserver
    Antworten: 4
    Letzter Beitrag: 03.01.07, 00:48