Java를 사용하여 인터넷에서 파일을 다운로드하고 저장하는 방법은 무엇입니까?
http://www.example.com/information.asp
디렉토리에 파일 을 가져 와서 저장해야하는 온라인 파일 (예 :)이 있습니다. 온라인 파일 (URL)을 한 줄씩 잡고 읽는 몇 가지 방법이 있지만 Java를 사용하여 파일을 다운로드하고 저장하는 방법이 있습니까?
부여 자바 NIO을 시도 :
URL website = new URL("http://www.website.com/information.asp");
ReadableByteChannel rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream("information.html");
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
사용 transferFrom()
하다 잠재적으로 훨씬 더 효율적인 소스 채널로부터 판독하고,이 채널을 쓰는 간단한 루프보다. 많은 운영 체제는 실제로 복사하지 않고 소스 채널에서 파일 시스템 캐시로 바이트를 직접 전송할 수 있습니다.
참고 : transferFrom의 세 번째 매개 변수는 전송할 최대 바이트 수입니다. Integer.MAX_VALUE
최대 2 ^ 31 바이트를 전송하고 최대 2 ^ Long.MAX_VALUE
63 바이트를 허용합니다 (존재하는 파일보다 큼).
한 줄의 코드만으로 apache commons-io를 사용하십시오 .
FileUtils.copyURLToFile(URL, File)
더 간단한 nio 사용법 :
URL website = new URL("http://www.website.com/information.asp");
try (InputStream in = website.openStream()) {
Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}
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 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);
}
오래된 질문이지만 올바르게 닫힌 리소스가있는 간결하고 읽기 쉬운 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));
}
}
두 줄의 코드로 종속성이 없습니다.
사용하는 경우 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;
}
이 답변은 선택된 답변과 거의 동일하지만 두 가지 개선 사항이 있습니다. 메서드이며 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();
}
}
import java.io.*;
import java.net.*;
public class filedown {
public static void download(String address, String localFileName) {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try {
URL url = new URL(address);
out = new BufferedOutputStream(new FileOutputStream(localFileName));
conn = url.openConnection();
in = conn.getInputStream();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1) {
out.write(buffer, 0, numRead);
numWritten += numRead;
}
System.out.println(localFileName + "\t" + numWritten);
}
catch (Exception exception) {
exception.printStackTrace();
}
finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
catch (IOException ioe) {
}
}
}
public static void download(String address) {
int lastSlashIndex = address.lastIndexOf('/');
if (lastSlashIndex >= 0 &&
lastSlashIndex < address.length() - 1) {
download(address, (new URL(address)).getFile());
}
else {
System.err.println("Could not figure out local file name for "+address);
}
}
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
download(args[i]);
}
}
}
개인적으로, Apache의 HttpClient 는 이것과 관련하여 필요한 모든 것을 능가하는 것으로 나타났습니다 . 다음 은 HttpClient 사용에 대한 훌륭한 자습서입니다.
이것은 try-with 문을 사용한 Brian Risk의 답변 을 기반으로 한 또 다른 java7 변형입니다 .
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);
}
}
여기에는 많은 우아하고 효율적인 답변이 있습니다. 그러나 간결함은 유용한 정보를 잃을 수 있습니다. 특히, 연결 오류를 예외로 간주하지 않으려는 경우가 있으며, 다운로드를 다시 시도해야하는지 여부를 결정하기 위해 네트워크 관련 오류를 다르게 처리하려고 할 수 있습니다.
다음은 네트워크 오류에 대한 예외를 발생시키지 않는 방법입니다 (잘못된 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;
}
간단한 사용법에는 다음과 같은 문제가 있습니다.
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();
}
HttpComponents
대신 Apache를 사용하여 파일을 다운로드 할 수 있습니다 Commons-IO
. 이 코드를 사용하면 URL에 따라 Java로 파일을 다운로드하여 특정 대상에 저장할 수 있습니다.
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
값 을 지정할 수 있습니다.
이전 답변을 요약하고 어떻게 든 연마하고 업데이트하십시오. 다음 세 가지 방법은 실질적으로 동일합니다. (필수 시간이라고 생각하기 때문에 명시 적 시간 초과를 추가했으며, 연결이 끊어지면 다운로드가 영원히 멈추기를 원하지 않습니다.)
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();
}
나는 중요한 차이점을 찾지 못합니다. 안전하고 효율적입니다. (속도의 차이는 거의 관련이없는 것 같습니다-1.2 ~ 1.5 segs 변동하는 시간에 로컬 서버에서 SSD 디스크에 180Mb를 씁니다). 외부 라이브러리가 필요하지 않습니다. 모든 것은 임의의 크기와 (내 경험에 따르면) HTTP 리디렉션으로 작동합니다.
또한 FileNotFoundException
리소스를 찾을 수없는 경우 (일반적으로 오류 404) java.net.UnknownHostException
DNS 확인에 실패한 경우 모두 throw 됩니다 . 다른 IOException은 전송 중 오류에 해당합니다.
(커뮤니티 위키로 표시, 정보 또는 수정 사항을 자유롭게 추가하십시오)
밑줄-자바 라이브러리 에는 U.fetch (url) 메소드가 있습니다.
pom.xml :
<groupId>com.github.javadev</groupId>
<artifactId>underscore</artifactId>
<version>1.45</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();
}
}
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;
}
}
netloader for Java를 사용하여 한 줄로 이를 수행 할 수 있습니다 .
new NetFile(new File("my/zips/1.zip"), "https://example.com/example.zip", -1).load(); //returns true if succeed, otherwise false.
프록시 뒤에있는 경우 다음과 같이 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();
}
}
다음은 자바 코드로 인터넷에서 영화를 다운로드하는 샘플 코드입니다.
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);
}
참고 URL : https://stackoverflow.com/questions/921262/how-to-download-and-save-a-file-from-internet-using-java
'Programing' 카테고리의 다른 글
Nginx — 루트 및 별칭과 혼동되는 정적 파일 (0) | 2020.02.21 |
---|---|
버튼 텍스트가 Lollipop의 모든 캡으로 강제되는 이유는 무엇입니까? (0) | 2020.02.21 |
Apple의 Swift 언어에서 난수를 어떻게 생성합니까? (0) | 2020.02.20 |
SSH 키-여전히 비밀번호 및 비밀번호 문구 요청 (0) | 2020.02.20 |
Git 저장소에서 특정 작성자가 변경 한 총 줄 수를 계산하는 방법은 무엇입니까? (0) | 2020.02.20 |