Pour résumer (et en quelque sorte peaufiner et mettre à jour) les réponses précédentes. Les trois méthodes suivantes sont pratiquement équivalentes. (J'ai ajouté des délais d'attente explicites parce que je pense qu'ils sont indispensables, personne ne veut qu'un téléchargement se fige pour toujours lorsque la connexion est perdue.)
public static void saveUrl1(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout))
throws MalformedURLException, IOException {
// Files.createDirectories(file.getParent()); // optional, make sure parent dir exists
try (BufferedInputStream in = new BufferedInputStream(
streamFromUrl(url, secsConnectTimeout,secsReadTimeout) );
OutputStream fout = Files.newOutputStream(file)) {
final byte data[] = new byte[8192];
int count;
while((count = in.read(data)) > 0)
fout.write(data, 0, count);
}
}
public static void saveUrl2(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout))
throws MalformedURLException, IOException {
// Files.createDirectories(file.getParent()); // optional, make sure parent dir exists
try (ReadableByteChannel rbc = Channels.newChannel(
streamFromUrl(url, secsConnectTimeout,secsReadTimeout)
);
FileChannel channel = FileChannel.open(file,
StandardOpenOption.CREATE,
StandardOpenOption.TRUNCATE_EXISTING,
StandardOpenOption.WRITE)
) {
channel.transferFrom(rbc, 0, Long.MAX_VALUE);
}
}
public static void saveUrl3(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout))
throws MalformedURLException, IOException {
// Files.createDirectories(file.getParent()); // optional, make sure parent dir exists
try (InputStream in = streamFromUrl(url, secsConnectTimeout,secsReadTimeout) ) {
Files.copy(in, file, StandardCopyOption.REPLACE_EXISTING);
}
}
public static InputStream streamFromUrl(URL url,int secsConnectTimeout,int secsReadTimeout) throws IOException {
URLConnection conn = url.openConnection();
if(secsConnectTimeout>0) conn.setConnectTimeout(secsConnectTimeout*1000);
if(secsReadTimeout>0) conn.setReadTimeout(secsReadTimeout*1000);
return conn.getInputStream();
}
Je ne trouve pas de différences significatives, tout me semble juste. Ils sont sûrs et efficaces. (Les différences de vitesse ne semblent guère pertinentes - j'écris 180 Mo du serveur local sur un disque SSD à des moments qui fluctuent entre 1,2 et 1,5 segs). Ils ne nécessitent pas de bibliothèques externes. Tous fonctionnent avec des tailles arbitraires et (selon mon expérience) des redirections HTTP.
De plus, tous lancent FileNotFoundException
si la ressource n'est pas trouvée (erreur 404, généralement), etjava.net.UnknownHostException
si la résolution DNS a échoué; les autres IOException correspondent à des erreurs lors de la transmission.
(Marqué comme wiki communautaire, n'hésitez pas à ajouter des informations ou des corrections)