Publié le 17/04/2013
Auteur Fobec
Réseaux sociaux
0 partages
0 tweets
0 plus
0 commentaires

Telecharger un fichier depuis une url

Dans les applications JAVA, mes requêtes utilisent HttpURLConnection pour ouvrir les connexions aux serveurs internet. Au fil du temps, les class se sont multipliées pour traiter les redirections (la solution utilisée par HttpURLConnection est bof-bof), les connexions cryptées Https et le traitement des erreurs.
L'ensemble des fonctions est regroupé dans la class HttpFileDownloader.

Envoyer une requete Http avec HttpURLConnection

Certaines fonctions sont automatiques et sont directement réglées par la class en interne. A titre d'exemple, le passage vers une connexion sécurisée https, la redirection vers une autre URL et les contenus incomplets.
En intégrant HttpFileDownloader dans une application, vous pouvez fixer et obtenir les données suivantes:
- getHeader(): retourne l'entete du fichier contenant toutes les données,
- getResponseCode(): retourne le code HTTP. Lorsqu'il est différent de 200, le code fournit une piste pour le débugage,
- getURL(): retourne l'URL de téléchargement. Elle peut etre différente de l'URL passé dans le constructeur en cas de redirection,
- getTimeConnect(): retourne le temps de connexion au serveur,
- getTimeDownload(): retourne le temps de téléchargement,
- setUserAgent(): fixe le UserAgent utilisé pour la requête.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.activation.UnsupportedDataTypeException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
 
/**
 * Télécharger un fichier depuis une url
 * @author Fobec 2013
 * @see http://www.fobec.com/java/1125/telecharger-fichier-depuis-une-url.html
 */
public class HttpFileDownloader {
 
    private String urlPath;
    private String ua = null; //user Agent
    private int respondeCode = -1; //http://fr.wikipedia.org/wiki/Liste_des_codes_HTTP
    private Map headerFields; //entete
    private long time_start; //debut de connexion
    private long time_connect; //debut de transfert
    private long time_end; //fin
 
    /**
     * Constructeur
     * @param url
     */
    public HttpFileDownloader(String url) {
        this.urlPath = url;
    }
 
    /**
     * Charger le contenu au format texte
     * @return String
     */
    public String asString() throws IOException, NoSuchAlgorithmException, KeyManagementException {
        BufferedReader reader = null;
        String html = "";
        try {
            HttpURLConnection curl = (HttpURLConnection) open();
            //Seul le format texte est accepté
            String contentType = curl.getContentType();
            if (!contentType.startsWith("text/")) {
                throw new UnsupportedDataTypeException("Bad format, only text can be loaded");
            }
 
            reader = new BufferedReader(new InputStreamReader(curl.getInputStream()));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
                sb.append(System.getProperty("line.separator"));
            }
            html = sb.toString();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
        return html;
    }
 
    /**
     * Enregistrer fichier en conservant le nom
     * @param destPath String répertoire local
     */
    public void savetoFile(String destPath) throws IOException, NoSuchAlgorithmException,
            KeyManagementException {
        savetoFile(destPath, null);
    }
 
    /**
     * Enregistrer fichier, nom en local différent
     * @param destPath String répertoire local
     * @param destFilename String nom du fichier local
     */
    public void savetoFile(String destPath, String destFilename) throws IOException, 
            NoSuchAlgorithmException, KeyManagementException {
        RandomAccessFile outFile = null;
        InputStream inStream = null;
        byte[] buffer = new byte[4096];
        int bufferLength = - 1;
        String filename;
        if (destFilename == null) {
            filename = this.urlPath.substring(this.urlPath.lastIndexOf('/') + 1);
        } else {
            filename = destFilename;
        }
 
        HttpURLConnection curl = open();
        int sizeExpect = curl.getContentLength();
        int sizeFile = 0;
 
        try {
            outFile = new RandomAccessFile(destPath + filename, "rw");
            inStream = curl.getInputStream();
            while ((bufferLength = inStream.read(buffer)) != -1) {
                outFile.write(buffer, 0, bufferLength);
                sizeFile += bufferLength;
            }
            this.time_end = System.currentTimeMillis();
 
            if (sizeExpect != -1 && sizeFile != sizeExpect) {
                this.respondeCode = 406;
                throw new IOException("Partial Contents - Expect " + sizeExpect 
                        + " bytes; download " + sizeFile + " bytes");
            }
        } finally {
            outFile.close();
            inStream.close();
        }
    }
 
    /**
     * Entete de la ressource retourné par le serveur
     * @return String
     */
    public String getHeader() {
        StringBuilder sb = new StringBuilder();
        Set headers = this.headerFields.entrySet();
        for (Iterator i = headers.iterator(); i.hasNext();) {
            Map.Entry map = (Map.Entry) i.next();
            if (map.getKey() != null) {
                sb.append(map.getKey() + " : " + map.getValue() + "n");
            }
        }
        return sb.toString();
    }
 
    /**
     * Code réponse du serveur
     * @see http://fr.wikipedia.org/wiki/Liste_des_codes_HTTP
     * @return int
     */
    public int getResponseCode() {
        return this.respondeCode;
    }
 
    public String getURL() {
        return this.urlPath;
    }
 
    /**
     * Temps de connexion
     * @return int milliseconde
     */
    public long getTimeConnect() {
        long t = this.time_connect - this.time_start;
        return t;
    }
 
    /**
     * Duree du téléchargment
     * @return int milliseconde
     */
    public long getTimeDownload() {
        long t = this.time_end - this.time_connect;
        return t;
    }
 
    /**
     * Fixer le user Agent de la requete
     * @param useragent
     */
    public void setUserAgent(String useragent) {
        this.ua = useragent;
    }
 
    /**
     * Ouvrir une connexion http ou https
     * @return HttpURLConnection
     */
    private HttpURLConnection open() throws NoSuchAlgorithmException, 
            KeyManagementException, MalformedURLException, IOException {
        this.time_start = System.currentTimeMillis();
        URL url;
        HttpURLConnection curl = null;
 
        url = new URL(this.urlPath);
        if (this.urlPath.startsWith("https")) {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{new MyTrustManager()}, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new MyHostnameVerifier());
            curl = (HttpsURLConnection) new URL(this.urlPath).openConnection();
        } else {
            curl = (HttpURLConnection) url.openConnection();
        }
 
        if (this.ua != null) {
            curl.setRequestProperty("User-Agent", this.ua);
        }
        curl.setRequestMethod("GET");
        curl.setReadTimeout(5000);
        curl.setInstanceFollowRedirects(true);        
 
        this.respondeCode = curl.getResponseCode();
        this.headerFields = curl.getHeaderFields();
 
        if (this.respondeCode != 200) {
            //Redirection sur les 301 + 302 + 303
            if (this.respondeCode > 300 && this.respondeCode < 304) {
                this.urlPath = curl.getHeaderField("Location");
                return this.open();
            } else {
                throw new MalformedURLException("wrong answer on URL "+this.urlPath);
            }
        }
        this.time_connect = System.currentTimeMillis();
        return curl;
    }
 
    /**
     * Override class SSL
     */
    private class MyHostnameVerifier implements HostnameVerifier {
 
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
 
    /**
     * Override class SSL
     */
    private class MyTrustManager implements X509TrustManager {
 
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
        }
 
        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
        }
 
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }
    }
}

Exemple 1: Charger le code source d'une page HTML

Chargeons le code source de la page HTML de Twitter.Com dans un String.
L'opération est plus complexe qu'elle n'y parait, à savoir une redirection de http://www.twitter.com vers https://www.twitter.com et l'ouverture d'une connexion cryptée https pour charger le code source.
import core.HttpFileDownloader;
import java.util.logging.Level;
import java.util.logging.Logger;
 
public class Main {
    public static void main(String[] args) {
        HttpFileDownloader loader = new HttpFileDownloader("http://www.twitter.com");
        try {
            loader.setUserAgent("Demo HttpFileDownloader");
            String html = loader.asString();
            System.out.println("code http: "+loader.getResponseCode());
            System.out.println("URL: "+loader.getURL());
           // System.out.println(loader.getHeader());
            System.out.println("temps connexion:"+loader.getTimeConnect()+" ms");
            System.out.println("temps telechargement:"+loader.getTimeDownload()+" ms");
            System.out.println("code source de la page"+html);
        } catch (Exception ex) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
Console Java
code http: 200
URL: https://twitter.com/
temps connexion:1860 ms
temps telechargement:390 ms
code source de la page<!DOCTYPE html>....

Exemple 2: traiter les erreurs

Une requête sur un serveur internet n'aboutit pas à chaque fois. Dans cet exemple, voyons comment intercepter et traiter une URL incorrecte, la fameuse erreur 404.
import core.HttpFileDownloader;
 
public class Main {
    public static void main(String[] args) {
        String myURL="http://www.commentcamarche.net/jenexistepas.html";
        HttpFileDownloader loader = new HttpFileDownloader(myURL);
        try {
            loader.setUserAgent("Demo HttpFileDownloader");
            String html = loader.asString();  
        } catch (Exception ex) {
            System.err.println("Chargement de "+loader.getURL());
            System.err.println("La requete a generée une exception "+loader.getResponseCode());
        }
    }
}

Console

Chargement de http://www.commentcamarche.net/jenexistepas.html
La requete a generée une exception 404

Exemple 3: Enregistrer une requete Google dans un fichier

Par défaut, l'enregistrement d'une ressource s'effectue avec la fonction savetoFile(String destPath), le nom du fichier d'origine est conservé. Dans ce cas, le nom du fichier serait refusé par l'OS search?q=mes+prochaines+vacances. C'est pourquoi HttpFileDownloader dispose d'une variante pour déterminer le nom du fichier en local.
import core.HttpFileDownloader;
 
public class Main {
    public static void main(String[] args) {
        String myURL="https://www.google.com/search?q=mes+prochaines+vacances";
        HttpFileDownloader loader = new HttpFileDownloader(myURL);
        try {
            loader.setUserAgent("Demo HttpFileDownloader");
            loader.savetoFile("C://", "reqGoogle.html");
            System.err.println(loader.getResponseCode()+" - 200 signifie tout est nickel");
        } catch (Exception ex) {
            System.err.println("La requete a generée une exception "+loader.getResponseCode());
        }
    }
}
Résultat

Sur votre disque dur se trouve un fichier html ayant pour nom C:/reqGoogle.html ou /home/mydesktop/reqGoogle.html.

Ajouter un commentaire

Les champs marqués d'un * sont obligatoires, les adresses emails se sont pas publiées.

A lire aussi

Réseaux sociaux
Présentation de l'article
Catégorie
java - sources
Mise a jour
17/04/2013
Visualisation
vu 5527 fois
Public
Internaute
Auteur de la publication
Fobec
Admin
Auteur de 267 articles
|BIO_PSEUDO|
Commentaires récents

Publié par stux dans java

Génial.. C'est exactement ce que je cherchais.

Publié par traitstone dans CMS

c'est bou et tres bon chose

Publié par medfayz dans java

hi everybody thanks for the code , and please can any one help me to fix that exception.
javax.media.NoPlayerException: Cannot find a Player for :vfw:0

thanks

Publié par IB dans tuto

Merci ca marche bien.

Publié par aalex57 dans tuto

Bonsoir,

Merci pour l'astuce, cependant votre fichier php ne fonctionne pas chez moi.
Il m'indique une erreur à la ligne 16 :/