Если вы используете C # 7, вы можете использовать удобный метод обертки, подобный этому ...
public static class TaskEx
{
public static async Task<(T1, T2)> WhenAll<T1, T2>(Task<T1> task1, Task<T2> task2)
{
await Task.WhenAll(task1, task2);
return (task1.Result, task2.Result);
}
}
..., чтобы включить удобный синтаксис, подобный этому, когда вы хотите ждать нескольких задач с разными типами возврата. Конечно, вам придется сделать несколько перегрузок для разного количества задач.
var (someInt, someString) = await TaskEx.WhenAll(GetIntAsync(), GetStringAsync());
Это старый вопрос, но вот элегантное решение JDK:
public static void download(String url, String fileName) throws Exception {
try (InputStream in = URI.create(url).toURL().openStream()) {
Files.copy(in, Paths.get(fileName));
}
}
Краткий, читаемый, правильно закрытый ресурс, не использующий ничего, кроме основных функций JDK и языка.
Подводя итоги (и как-то отполировать и обновлять) предыдущие ответы. Три следующих метода практически эквивалентны. (Я добавил явные тайм-ауты, потому что я думаю, что они необходимы, никто не хочет, чтобы загрузка зависала навсегда, когда соединение потеряно.)
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.
Кроме того, все throw FileNotFoundException
, если ресурс не найден (ошибка 404, обычно) и java.net.UnknownHostException
, если ошибка DNS не удалась ; другое IOException соответствует ошибкам во время передачи.
(Помечается как wiki сообщества, не стесняйтесь добавлять информацию или исправления)
Лично я нашел HttpClient Apache более чем способным ко всему, что мне нужно было сделать в отношении этого. Здесь - отличный учебник по использованию HttpClient
Если вы находитесь за прокси-сервером, вы можете установить прокси-серверы в java-программе, как показано ниже:
Properties systemSettings = System.getProperties();
systemSettings.put("proxySet", "true");
systemSettings.put("https.proxyHost", "https proxy of your org");
systemSettings.put("https.proxyPort", "8080");
Если вы не находитесь за прокси-сервером, не указывайте строки выше в своем коде. Полный рабочий код для загрузки файла, когда вы находитесь за прокси.
public static void main(String[] args) throws IOException {
String url="https://raw.githubusercontent.com/bpjoshi/fxservice/master/src/test/java/com/bpjoshi/fxservice/api/TradeControllerTest.java";
OutputStream outStream=null;
URLConnection connection=null;
InputStream is=null;
File targetFile=null;
URL server=null;
//Setting up proxies
Properties systemSettings = System.getProperties();
systemSettings.put("proxySet", "true");
systemSettings.put("https.proxyHost", "https proxy of my organisation");
systemSettings.put("https.proxyPort", "8080");
//The same way we could also set proxy for http
System.setProperty("java.net.useSystemProxies", "true");
//code to fetch file
try {
server=new URL(url);
connection = server.openConnection();
is = connection.getInputStream();
byte[] buffer = new byte[is.available()];
is.read(buffer);
targetFile = new File("src/main/resources/targetFile.java");
outStream = new FileOutputStream(targetFile);
outStream.write(buffer);
} catch (MalformedURLException e) {
System.out.println("THE URL IS NOT CORRECT ");
e.printStackTrace();
} catch (IOException e) {
System.out.println("Io exception");
e.printStackTrace();
}
finally{
if(outStream!=null) outStream.close();
}
}
Этот ответ почти точно подобен выбранному ответу, но с двумя улучшениями: это метод и он закрывает объект FileOutputStream:
public static void downloadFileFromURL(String urlString, File destination) {
try {
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
} catch (IOException e) {
e.printStackTrace();
}
}
transferFrom()
isnt 'указан для завершения всей передачи за один раз. Вот почему он возвращает счет. Вы должны зациклиться.
– user207421
5 July 2016 в 09:30
При использовании Java 7+
используйте следующий метод для загрузки файла из Интернета и сохранения его в какой-либо каталог:
private static Path download(String sourceURL, String targetDirectory) throws IOException
{
URL url = new URL(sourceURL);
String fileName = sourceURL.substring(sourceURL.lastIndexOf('/') + 1, sourceURL.length());
Path targetPath = new File(targetDirectory + File.separator + fileName).toPath();
Files.copy(url.openStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
return targetPath;
}
Документация здесь .
Вы можете сделать это в 1 строке, используя netloader для Java :
new NetFile(new File("my/zips/1.zip"), "https://example.com/example.zip", -1).load(); //returns true if succeed, otherwise false.
Это еще один вариант java7, основанный на ответе Брайана Риск с использованием инструкции try-with:
public static void downloadFileFromURL(String urlString, File destination) throws Throwable {
URL website = new URL(urlString);
try(
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
){
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
}
}
transferFrom()
isnt 'указан для завершения всей передачи за один раз. Вот почему он возвращает счет. Вы должны зациклиться.
– user207421
5 July 2016 в 09:30
public class DownloadManager {
static String urls = "[WEBSITE NAME]";
public static void main(String[] args) throws IOException{
URL url = verify(urls);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
InputStream in = null;
String filename = url.getFile();
filename = filename.substring(filename.lastIndexOf('/') + 1);
FileOutputStream out = new FileOutputStream("C:\\Java2_programiranje/Network/DownloadTest1/Project/Output" + File.separator + filename);
in = connection.getInputStream();
int read = -1;
byte[] buffer = new byte[4096];
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
System.out.println("[SYSTEM/INFO]: Downloading file...");
}
in.close();
out.close();
System.out.println("[SYSTEM/INFO]: File Downloaded!");
}
private static URL verify(String url){
if(!url.toLowerCase().startsWith("http://")) {
return null;
}
URL verifyUrl = null;
try{
verifyUrl = new URL(url);
}catch(Exception e){
e.printStackTrace();
}
return verifyUrl;
}
}
public void saveUrl(final String filename, final String urlString)
throws MalformedURLException, IOException {
BufferedInputStream in = null;
FileOutputStream fout = null;
try {
in = new BufferedInputStream(new URL(urlString).openStream());
fout = new FileOutputStream(filename);
final byte data[] = new byte[1024];
int count;
while ((count = in.read(data, 0, 1024)) != -1) {
fout.write(data, 0, count);
}
} finally {
if (in != null) {
in.close();
}
if (fout != null) {
fout.close();
}
}
}
Вам нужно будет обрабатывать исключения, возможно, внешние для этого метода.
BufferedInputStream
имеет точно нулевой эффект на тайм-аутах сокета. Я уже опроверг это как «городской миф» в своих комментариях к «справочным данным», которые вы указали. Три года назад.
– user207421
23 July 2014 в 03:33
BufferedInputStream
"может вызвать непредсказуемые сбои & quot;).
– ComFreek
24 July 2014 в 16:53
Здесь много элегантных и эффективных ответов. Но краткость может заставить нас потерять какую-то полезную информацию. В частности, часто не хочется рассматривать ошибку соединения как «Исключение», и можно было бы по-разному относиться к каким-либо связанным с сетью ошибкам - например, решить, следует ли повторить загрузку.
Вот метод, который не вызывает исключения для сетевых ошибок (только для действительно исключительных проблем, таких как неверный URL-адрес или проблемы с записью в файл)
/**
* Downloads from a (http/https) URL and saves to a file.
* Does not consider a connection error an Exception. Instead it returns:
*
* 0=ok
* 1=connection interrupted, timeout (but something was read)
* 2=not found (FileNotFoundException) (404)
* 3=server error (500...)
* 4=could not connect: connection timeout (no internet?) java.net.SocketTimeoutException
* 5=could not connect: (server down?) java.net.ConnectException
* 6=could not resolve host (bad host, or no internet - no dns)
*
* @param file File to write. Parent directory will be created if necessary
* @param url http/https url to connect
* @param secsConnectTimeout Seconds to wait for connection establishment
* @param secsReadTimeout Read timeout in seconds - trasmission will abort if it freezes more than this
* @return See above
* @throws IOException Only if URL is malformed or if could not create the file
*/
public static int saveUrl(final Path file, final URL url,
int secsConnectTimeout, int secsReadTimeout) throws IOException {
Files.createDirectories(file.getParent()); // make sure parent dir exists , this can throw exception
URLConnection conn = url.openConnection(); // can throw exception if bad url
if( secsConnectTimeout > 0 ) conn.setConnectTimeout(secsConnectTimeout * 1000);
if( secsReadTimeout > 0 ) conn.setReadTimeout(secsReadTimeout * 1000);
int ret = 0;
boolean somethingRead = false;
try (InputStream is = conn.getInputStream()) {
try (BufferedInputStream in = new BufferedInputStream(is); OutputStream fout = Files
.newOutputStream(file)) {
final byte data[] = new byte[8192];
int count;
while((count = in.read(data)) > 0) {
somethingRead = true;
fout.write(data, 0, count);
}
}
} catch(java.io.IOException e) {
int httpcode = 999;
try {
httpcode = ((HttpURLConnection) conn).getResponseCode();
} catch(Exception ee) {}
if( somethingRead && e instanceof java.net.SocketTimeoutException ) ret = 1;
else if( e instanceof FileNotFoundException && httpcode >= 400 && httpcode < 500 ) ret = 2;
else if( httpcode >= 400 && httpcode < 600 ) ret = 3;
else if( e instanceof java.net.SocketTimeoutException ) ret = 4;
else if( e instanceof java.net.ConnectException ) ret = 5;
else if( e instanceof java.net.UnknownHostException ) ret = 6;
else throw e;
}
return ret;
}
С помощью файла Apache HttpComponents
вместо Commons-IO
можно загрузить файл. Этот код позволяет загружать файл на Java в соответствии с его URL-адресом и сохранять его в определенном месте назначения.
public static boolean saveFile(URL fileURL, String fileSavePath) {
boolean isSucceed = true;
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(fileURL.toString());
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0");
httpGet.addHeader("Referer", "https://www.google.com");
try {
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
HttpEntity fileEntity = httpResponse.getEntity();
if (fileEntity != null) {
FileUtils.copyInputStreamToFile(fileEntity.getContent(), new File(fileSavePath));
}
} catch (IOException e) {
isSucceed = false;
}
httpGet.releaseConnection();
return isSucceed;
}
В отличие от одной строки кода:
FileUtils.copyURLToFile(fileURL, new File(fileSavePath),
URLS_FETCH_TIMEOUT, URLS_FETCH_TIMEOUT);
этот код даст вам больше контроля над процессом и позволит вам указать не только тайм-ауты, но User-Agent
и Referer
значения, которые имеют решающее значение для многих веб-сайтов.
Существует проблема с простым использованием:
org.apache.commons.io.FileUtils.copyURLToFile(URL, File)
, если вам нужно загружать и сохранять очень большие файлы, или вообще, если вам нужны автоматические повторы в случае отказа соединения.
В таких случаях я предлагаю Apache HttpClient вместе с org.apache.commons.io.FileUtils. Например:
GetMethod method = new GetMethod(resource_url);
try {
int statusCode = client.executeMethod(method);
if (statusCode != HttpStatus.SC_OK) {
logger.error("Get method failed: " + method.getStatusLine());
}
org.apache.commons.io.FileUtils.copyInputStreamToFile(
method.getResponseBodyAsStream(), new File(resource_file));
} catch (HttpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
method.releaseConnection();
}
Используйте apache commons-io , только один код строки:
FileUtils.copyURLToFile(URL, File)
copyURLToFile
с параметром таймаута доступен только с версии 2.0 библиотеки Commons IO. См. Java docs
– Stanley
12 April 2013 в 05:00
Упрощенное использование nio:
URL website = new URL("http://www.website.com/information.asp");
try (InputStream in = website.openStream()) {
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}
InputStream.read()
возвращал ноль, если вы не предоставили буфер или счетчик нулевой длины, «небольшую паузу» или иначе. Он будет блокироваться до тех пор, пока не будет передан хотя бы один байт или конец потока или не произойдет ошибка. Ваше утверждение о внутренних функциях Files.copy()
необоснованно.
– user207421
5 July 2016 в 09:26
Ниже приведен пример кода для загрузки фильма из Интернета с помощью java-кода:
URL url = new
URL("http://103.66.178.220/ftp/HDD2/Hindi%20Movies/2018/Hichki%202018.mkv");
BufferedInputStream bufferedInputStream = new BufferedInputStream(url.openStream());
FileOutputStream stream = new FileOutputStream("/home/sachin/Desktop/test.mkv");
int count=0;
byte[] b1 = new byte[100];
while((count = bufferedInputStream.read(b1)) != -1) {
System.out.println("b1:"+b1+">>"+count+ ">> KB downloaded:"+new File("/home/sachin/Desktop/test.mkv").length()/1024);
stream.write(b1, 0, count);
}
Загрузка файла требует, чтобы вы его прочитали, в любом случае вам придется каким-то образом пройти через файл. Вместо строки за строкой вы можете просто прочитать ее байтами из потока:
BufferedInputStream in = new BufferedInputStream(new URL("http://www.website.com/information.asp").openStream())
byte data[] = new byte[1024];
int count;
while((count = in.read(data,0,1024)) != -1)
{
out.write(data, 0, count);
}
В библиотеке underscore-java имеется метод U.fetch (url).
pom.xml:
<groupId>com.github.javadev</groupId>
<artifactId>underscore</artifactId>
<version>1.35</version>
Пример кода:
import com.github.underscore.lodash.U;
public class Download {
public static void main(String ... args) {
String text = U.fetch("https://stackoverflow.com/questions"
+ "/921262/how-to-download-and-save-a-file-from-internet-using-java").text();
}
}
Java
, но ваш ответ выглядит как JavaScript
– talex
25 July 2017 в 12:10
8388608
TB? – Cruncher 15 October 2013 в 15:02transferFrom()
isnt 'указан для завершения всей передачи за один раз. Вот почему он возвращает счет. Вы должны зациклиться. – user207421 23 July 2014 в 03:32