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);
}
}
}
code http: 200
URL: https://twitter.com/
temps connexion:1860 ms
temps telechargement:390 ms
code source de la page<!DOCTYPE html>....
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
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());
}
}
}
Sur votre disque dur se trouve un fichier html ayant pour nom C:/reqGoogle.html ou /home/mydesktop/reqGoogle.html.