Riassumere (e in qualche modo lucidare e aggiornare) le risposte precedenti. I tre metodi seguenti sono praticamente equivalenti. (Ho aggiunto timeout espliciti perché penso che siano indispensabili, nessuno vuole che un download si blocchi per sempre quando si perde la connessione.)
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();
}
Non trovo differenze significative, mi sembrano tutte giuste. Sono sicuri ed efficienti. (Le differenze di velocità sembrano poco rilevanti: scrivo 180 Mb dal server locale su un disco SSD in tempi che oscillano tra 1,2 e 1,5 secondi). Non richiedono librerie esterne. Tutti funzionano con dimensioni arbitrarie e (per la mia esperienza) reindirizzamenti HTTP.
Inoltre, tutti lanciano FileNotFoundException
se la risorsa non viene trovata (errore 404, in genere) e java.net.UnknownHostException
se la risoluzione DNS non è riuscita; altra IOException corrisponde ad errori durante la trasmissione.
(Contrassegnato come wiki della community, sentiti libero di aggiungere informazioni o correzioni)