Узагальнити (і якось відполірувати та оновити) попередні відповіді. Три наступні методи практично рівнозначні. (Я додав явні тайм-аути, тому що вважаю, що вони необхідні; ніхто не хоче, щоб завантаження завісило назавжди, коли зв’язок втрачено.)
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();
}
Я не знаходжу значних відмінностей, мені все здається правильним. Вони безпечні та ефективні. (Відмінності в швидкості здаються навряд чи актуальними - я записую 180 Мб з локального сервера на SSD диск у часи, що коливаються приблизно від 1,2 до 1,5 секунд). Вони не потребують зовнішніх бібліотек. Всі роботи з довільними розмірами та (на мій досвід) перенаправленнями HTTP.
Крім того, все кидати, FileNotFoundException
якщо ресурс не знайдено (помилка 404, як правило), і java.net.UnknownHostException
якщо роздільна здатність DNS не вдалася; інші IOException відповідають помилкам під час передачі.
(Позначена як вікі спільноти, сміливо додайте інформацію або виправлення)