Podsumowując (i jakoś dopracowując i aktualizując) poprzednie odpowiedzi. Trzy następujące metody są praktycznie równoważne. (Dodałem wyraźne limity czasu, ponieważ uważam, że są koniecznością, nikt nie chce, aby pobieranie zawieszało się na zawsze po utracie połączenia).
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();
}
Nie widzę istotnych różnic, wszystko wydaje mi się właściwe. Są bezpieczne i wydajne. (Różnice prędkości wydają się mało istotne - zapisuję 180 MB z lokalnego serwera na dysk SSD w czasach, które wahają się w granicach od 1,2 do 1,5 seg). Nie wymagają zewnętrznych bibliotek. Wszystkie działają z dowolnymi rozmiarami i (według mojego doświadczenia) przekierowaniami HTTP.
Ponadto wszystkie rzucają, FileNotFoundException
jeśli zasób nie zostanie znaleziony (zwykle błąd 404), orazjava.net.UnknownHostException
jeśli nie powiodło się rozstrzyganie DNS; inne wyjątki IOException odpowiadają błędom podczas transmisji.
(Oznaczone jako wiki społeczności, dodaj informacje lub poprawki)