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.
Réponses
Trop de publicités?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.
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));
}
}
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);
}
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.