Frage

Ich bin extrem neuen auf Java, und haben meist nur mich unterrichtet, wie ich gehe, also habe ich begonnen, ein Applet zu bauen. Ich mag machen, die eine Datei von der lokalen Festplatte auswählen können und laden Sie sie als multipart / form-data POST-Anforderung aber mit einem Fortschrittsbalken . Offensichtlich hat der Benutzer Zugriff auf das Java-Applet zu gewähren, um die Festplatte zuzugreifen. Jetzt habe ich schon den ersten Teil arbeiten: der Benutzer kann eine Datei auswählen JFileChooser Objekt verwenden, die bequem ein File Objekt zurückgibt. Aber ich frage mich, was als nächstes kommt. Ich weiß, dass File.length() mir die Gesamtgröße in Bytes der Datei geben, aber wie kann ich das ausgewählte File auf die Bahn schicken, und wie kann ich beobachten, wie viele Bytes gesendet wurde? Vielen Dank im Voraus.

War es hilfreich?

Lösung 3

beenden ich auf einem Open-Source-Java-Applet Uploader Stolpern und fand alles, was ich in ihrem Code wissen musste. Hier sind Links zu einer Blog-Post als auch die Quelle der Beschreibung:

Artikel
Source Code

Andere Tipps

Fortschritt zu überprüfen Httpclient verwenden, wickeln Sie das MultipartRequestEntity um eine, die die Bytes zählt gesendet werden. Wrapper ist unter:

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.commons.httpclient.methods.RequestEntity;

public class CountingMultipartRequestEntity implements RequestEntity {
    private final RequestEntity delegate;

    private final ProgressListener listener;

    public CountingMultipartRequestEntity(final RequestEntity entity,
            final ProgressListener listener) {
        super();
        this.delegate = entity;
        this.listener = listener;
    }

    public long getContentLength() {
        return this.delegate.getContentLength();
    }

    public String getContentType() {
        return this.delegate.getContentType();
    }

    public boolean isRepeatable() {
        return this.delegate.isRepeatable();
    }

    public void writeRequest(final OutputStream out) throws IOException {
        this.delegate.writeRequest(new CountingOutputStream(out, this.listener));
    }

    public static interface ProgressListener {
        void transferred(long num);
    }

    public static class CountingOutputStream extends FilterOutputStream {

        private final ProgressListener listener;

        private long transferred;

        public CountingOutputStream(final OutputStream out,
                final ProgressListener listener) {
            super(out);
            this.listener = listener;
            this.transferred = 0;
        }

        public void write(byte[] b, int off, int len) throws IOException {
            out.write(b, off, len);
            this.transferred += len;
            this.listener.transferred(this.transferred);
        }

        public void write(int b) throws IOException {
            out.write(b);
            this.transferred++;
            this.listener.transferred(this.transferred);
        }
    }
}

implementiert dann eine ProgressListener, die einen Fortschrittsbalken aktualisiert.
Denken Sie daran, dass der Fortschrittsbalken Update muss nicht auf dem Event Dispatch Thread ausgeführt werden.

Eine einfachere countingEntity würde nicht auf einem bestimmten Entitätstyp abhängen, sondern erweitert HttpEntityWrapped:

package gr.phaistos.android.util;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.http.HttpEntity;
import org.apache.http.entity.HttpEntityWrapper;

public class CountingHttpEntity extends HttpEntityWrapper {

    public static interface ProgressListener {
        void transferred(long transferedBytes);
    }


    static class CountingOutputStream extends FilterOutputStream {

        private final ProgressListener listener;
        private long transferred;

        CountingOutputStream(final OutputStream out, final ProgressListener listener) {
            super(out);
            this.listener = listener;
            this.transferred = 0;
        }

        @Override
        public void write(final byte[] b, final int off, final int len) throws IOException {
            //// NO, double-counting, as super.write(byte[], int, int) delegates to write(int).
            //super.write(b, off, len);
            out.write(b, off, len);
            this.transferred += len;
            this.listener.transferred(this.transferred);
        }

        @Override
        public void write(final int b) throws IOException {
            out.write(b);
            this.transferred++;
            this.listener.transferred(this.transferred);
        }

    }


    private final ProgressListener listener;

    public CountingHttpEntity(final HttpEntity entity, final ProgressListener listener) {
        super(entity);
        this.listener = listener;
    }

    @Override
    public void writeTo(final OutputStream out) throws IOException {
        this.wrappedEntity.writeTo(out instanceof CountingOutputStream? out: new CountingOutputStream(out, this.listener));
    }
}

Die Menge an Bytes, die vom Hörer zurück unterscheidet sich von der ursprünglichen Dateigröße. Anstatt also transferred++ zu haben, ich es geändert, so dass transferred=len; das ist die Länge der tatsächlichen Anzahl der Bytes in den Ausgabestrom geschrieben wird. Und wenn ich die Zugabe des gesamten Bytes berechnen übertrug es auf die tatsächliche ContentLength von CountingMultiPartEntity.this.getContentLength(); zurück gleich

public void write(byte[] b, int off, int len) throws IOException {
    wrappedOutputStream_.write(b,off,len);
    transferred=len;
    listener_.transferred(transferred);
}

Sie können diese Artikel hilfreich. Es erklärt im Detail unter Verwendung von Httpclient und Fileupload, beide Apache-Projekten zu tun, was Sie wollen. Es enthält auch Code-Beispiele.

Beachten Sie, dass die Fortschrittsbalken irreführend sein könnten, wenn eine Zwischenkomponente im Netzwerk (zum Beispiel eines ISP-HTTP-Proxy oder ein Reverse-HTTP-Proxy vor dem Server) verbraucht Upload schneller als der Server funktioniert.

Wie der Artikel bemerkt Vincent geschrieben, können Sie Apache commons, dies zu tun.

Little snipped


DiskFileUpload upload = new DiskFileUpload();
upload.setHeaderEncoding(ConsoleConstants.UTF8_ENCODING);

upload.setSizeMax(1000000);
upload.setSizeThreshold(1000000);

Iterator it = upload.parseRequest((HttpServletRequest) request).iterator();
FileItem item;
while(it.hasNext()){
    item = (FileItem) it.next();
    if (item.getFieldName("UPLOAD FIELD"){
       String fileName = item.getString(ConsoleConstants.UTF8_ENCODING);
       byte[] fileBytes = item.get();
    }
}

Just my 2c Wert:

Dieses basiert weg Antwort von tuler ist (hat einen Fehler zum Zeitpunkt des Schreibens). Ich änderte es leicht, hier so ist meine Version von tuler und mmyers Antwort (ich kann nicht scheinen, ihre Antwort zu bearbeiten). Das wollte ich etwas sauberer und schneller zu machen, um zu versuchen. Neben dem Fehler (die ich in den Kommentaren auf ihrer Antwort zu diskutieren), das große Problem, das ich mit ihrer Version ist, dass es ein neues CountingOutputStream mit jedem Schreib schafft. Dies kann sehr teuer in Bezug auf Speicher erhalten - Tonnen von Zuweisungen und Garbage Collection. Kleinere Problem ist, dass ein Delegierter verwendet, wenn er nur die MultipartEntity erweitern konnte. Nicht sicher, warum sie wählten, dass, so dass ich es in einer Art und Weise tat, war ich besser vertraut mit. Wenn jemand Vor / Nachteile der beiden Ansätze kennt, wäre toll. Schließlich ist die FilterOutputStream # write (byte [], int, int) -Methode nur ruft die FilterOutputStream # write (byte) in einer Schleife. Die FOS Dokumentation empfiehlt Subklassen überschrieben dieses Verhalten und macht diese effizienter zu gestalten. Der beste Weg, das hier zu tun ist, die zugrunde liegende Output behandelt die Schreibanforderung zu lassen.

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;

public class CountingMultiPartEntity extends MultipartEntity {

    private UploadProgressListener listener_;
    private CountingOutputStream outputStream_;
    private OutputStream lastOutputStream_;

    // the parameter is the same as the ProgressListener class in tuler's answer
    public CountingMultiPartEntity(UploadProgressListener listener) {
        super(HttpMultipartMode.BROWSER_COMPATIBLE);
        listener_ = listener;
    }

    @Override
    public void writeTo(OutputStream out) throws IOException {
        // If we have yet to create the CountingOutputStream, or the
        // OutputStream being passed in is different from the OutputStream used
        // to create the current CountingOutputStream
        if ((lastOutputStream_ == null) || (lastOutputStream_ != out)) {
            lastOutputStream_ = out;
            outputStream_ = new CountingOutputStream(out);
        }

        super.writeTo(outputStream_);
    }

    private class CountingOutputStream extends FilterOutputStream {

        private long transferred = 0;
            private OutputStream wrappedOutputStream_;

        public CountingOutputStream(final OutputStream out) {
            super(out);
                    wrappedOutputStream_ = out;
        }

        public void write(byte[] b, int off, int len) throws IOException {
                    wrappedOutputStream_.write(b,off,len);
                    ++transferred;
            listener_.transferred(transferred);
        }

        public void write(int b) throws IOException {
            super.write(b);
        }
    }
}

Schauen Sie in HTTP Client für uploadign die Datei im Web. Es sollte in der Lage sein, das zu tun. Ich bin nicht sicher, wie die Fortschrittsbalken zu bekommen, aber es würde bedeuten, irgendwie, dass die API abfragt.

Apache gemeinsam ist sehr gute Wahl. Apache gemeinsam ermöglicht es Ihnen, folgende Dinge zu konfigurieren.

  1. Konfigurieren (xml-Datei) die maximale Dateigröße / upload Dateigröße
  2. Zielpfad (wo die hochgeladene Datei speichern)
  3. Stellen Sie die Temperatur. Ordner, um die Datei zu tauschen, so dass Datei-Upload wäre schnell.

Von den anderen Antworten können Sie einfach überschreiben die AbstractHttpEntity Klasse Kinder oder Implementierungen public void writeTo(OutputStream outstream) Methode, die Sie verwenden, wenn nicht wollen, um eine Klasse erstellen.

Ein Beispiel einer FileEntity Instanz mit:

FileEntity fileEntity = new FileEntity(new File("img.jpg")){
    @Override
    public void writeTo(OutputStream outstream) throws IOException {
        super.writeTo(new BufferedOutputStream(outstream){
            int writedBytes = 0;

            @Override
            public synchronized void write(byte[] b, int off, int len) throws IOException {
                super.write(b, off, len);

                writedBytes+=len;
                System.out.println("wrote: "+writedBytes+"/"+getContentLength()); //Or anything you want [using other threads]
            }
        });
    }

};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top