Um frühere Antworten zusammenzufassen (und irgendwie zu polieren und zu aktualisieren). Die drei folgenden Methoden sind praktisch gleichwertig. (Ich habe explizite Zeitüberschreitungen hinzugefügt, weil ich denke, dass sie ein Muss sind. Niemand möchte, dass ein Download für immer einfriert, wenn die Verbindung unterbrochen wird.)
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();
}
Ich finde keine signifikanten Unterschiede, alle scheinen mir richtig zu sein. Sie sind sicher und effizient. (Geschwindigkeitsunterschiede scheinen kaum relevant zu sein - ich schreibe 180 MB vom lokalen Server auf eine SSD-Festplatte in Zeiten, die zwischen 1,2 und 1,5 Segmenten schwanken). Sie benötigen keine externen Bibliotheken. Alle arbeiten mit beliebigen Größen und (meiner Erfahrung nach) HTTP-Umleitungen.
Darüber hinaus werden alle ausgelöst, FileNotFoundException
wenn die Ressource nicht gefunden wird (normalerweise Fehler 404) und java.net.UnknownHostException
wenn die DNS-Auflösung fehlgeschlagen ist. andere IOException entsprechen Fehlern während der Übertragung.
(Als Community-Wiki markiert, können Sie gerne Informationen oder Korrekturen hinzufügen.)