Untuk meringkas (dan entah bagaimana memoles dan memperbarui) jawaban sebelumnya. Tiga metode berikut ini praktis setara. (Saya menambahkan batas waktu eksplisit karena saya pikir itu adalah keharusan, tidak ada yang mau unduhan dibekukan selamanya ketika koneksi terputus.)
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();
}
Saya tidak menemukan perbedaan yang signifikan, semuanya tampak benar bagi saya. Mereka aman dan efisien. (Perbedaan kecepatan tampaknya hampir tidak relevan - saya menulis 180MB dari server lokal ke disk SSD pada waktu yang berfluktuasi sekitar 1,2 hingga 1,5 seg). Mereka tidak memerlukan perpustakaan eksternal. Semua bekerja dengan ukuran sewenang-wenang dan (untuk pengalaman saya) pengalihan HTTP.
Selain itu, semua melempar FileNotFoundException
jika sumber daya tidak ditemukan (kesalahan 404, biasanya), danjava.net.UnknownHostException
jika resolusi DNS gagal; IOException lainnya berhubungan dengan kesalahan selama transmisi.
(Ditandai sebagai komunitas wiki, silakan tambahkan info atau koreksi)