30 votes

Téléchargement de fichiers avec Java (avec barre de progression)

Je suis très nouveau à Java, et ont pour la plupart été simplement l'enseignement de moi-même que je m'en vais, j'ai donc commencé la construction d'une applet. Je voudrais faire une qui permet de sélectionner un fichier à partir du disque local et de les télécharger sous forme d'un multipart/form-data requête POST, mais avec une barre de progression. Évidemment, l'utilisateur dispose d'octroi d'une autorisation de l'applet Java pour accéder au disque dur. Maintenant, j'ai déjà la première partie de travail: l'utilisateur peut sélectionner un fichier à l'aide d'un JFileChooser objet, idéalement renvoie une File objet. Mais je me demandais ce qui s'en vient. Je sais qu' File.length() va me donner la taille totale, en octets du fichier, mais comment puis-je envoyer la sélection d' File sur le web, et comment puis-je surveiller combien d'octets ont été envoyés? Merci à l'avance.

39voto

tuler Points 1131

Pour vérifier la progression à l'aide de HttpClient, encapsulez le MultipartRequestEntity autour de celui qui compte les octets envoyés. Wrapper est ci-dessous:

 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);
        }
    }
}
 

Implémente ensuite un ProgressListener qui met à jour une barre de progression.
N'oubliez pas que la mise à jour de la barre de progression ne doit pas s'exécuter sur le thread de répartition des événements.

12voto

ankostis Points 121

Une entité de comptage plus simple ne dépendrait pas d'un type d'entité spécifique mais étendrait plutôt 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));
    }
}
 

6voto

SoaperGEM Points 1311

J'ai fini par tomber sur un open source Java uploader applet et trouvé tout ce que je besoin de savoir au sein de son code. Voici des liens vers un article de blog en le décrivant, ainsi que la source:

L'Article
Le Code Source

5voto

user1358259 Points 81

La quantité d'octets retournés par l'écouteur est différente de la taille de fichier d'origine. Donc, au lieu d'avoir transferred++ , je l'ai modifié pour que transferred=len ; c'est la longueur de la quantité réelle d'octets en cours d'écriture dans le flux de sortie. Et lorsque je calcule l'addition du nombre total d'octets transférés, il est égal à la ContentLength réelle renvoyée par CountingMultiPartEntity.this.getContentLength();

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

4voto

Vincent Ramdhanie Points 46265

Vous pourriez trouver cet article utile. Il explique en détail en utilisant HttpClient et FileUpload, les deux projets apache pour faire ce que vous voulez. Il comprend également des exemples de code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X