programing

Java를 사용하여 인터넷에서 파일을 다운로드 및 저장하는 방법은 무엇입니까?

projobs 2022. 10. 21. 22:02
반응형

Java를 사용하여 인터넷에서 파일을 다운로드 및 저장하는 방법은 무엇입니까?

파일: " " )이 .http://www.example.com/information.asp를 가져와 디렉토리를 가져와 저장해야 합니다.온라인 파일(URL)을 한 줄씩 캡처하여 읽는 방법이 여러 가지가 있다는 것을 알고 있습니다만, Java를 사용하여 파일을 다운로드하여 저장하는 방법은 없습니까?

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" 을 합니다.Long.MAX_VALUE는 최대 2^63바이트를 허용합니다(존재하는 어떤 파일보다 큰 크기).

Apache Commons IO를 사용합니다.코드 한 줄에 불과합니다.

FileUtils.copyURLToFile(URL, File)

단순화된 논블로킹 I/O 사용:

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();
        }
    }
}

예외를 처리해야 합니다.아마도 이 메서드의 외부일 것입니다.

다음은 적절하게 닫힌 리소스를 갖춘 간결하고 읽기 쉬운 JDK 전용 솔루션입니다.

static long download(String url, String fileName) throws IOException {
    try (InputStream in = URI.create(url).toURL().openStream()) {
        return Files.copy(in, Paths.get(fileName));
    }
}

두 줄의 코드가 있고 종속성이 없습니다.

다음은 출력, 오류 검사 및 명령줄 인수 검사를 수행하는 완전한 파일다운로더 예제 프로그램입니다.

package so.downloader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Application {
    public static void main(String[] args) throws IOException {
        if (2 != args.length) {
            System.out.println("USAGE: java -jar so-downloader.jar <source-URL> <target-filename>");
            System.exit(1);
        }

        String sourceUrl = args[0];
        String targetFilename = args[1];

        long bytesDownloaded = download(sourceUrl, targetFilename);

        System.out.println(String.format("Downloaded %d bytes from %s to %s.", bytesDownloaded, sourceUrl, targetFilename));
    }

    static long download(String url, String fileName) throws IOException {
        try (InputStream in = URI.create(url).toURL().openStream()) {
            return Files.copy(in, Paths.get(fileName));
        }
    }    
}

SO-Downloader 저장소 README에서 설명한 바와 같이

파일 다운로드 프로그램을 실행하려면:

java -jar so-downloader.jar <source-URL> <target-filename>

예를 들어 다음과 같습니다.

java -jar so-downloader.jar https://github.com/JanStureNielsen/so-downloader/archive/main.zip so-downloader-source.zip

파일을 다운로드하려면 파일을 읽어야 합니다.어느 쪽이든 어떤 식으로든 파일을 검토해야 합니다.한 줄씩 읽는 대신 스트림에서 바이트 단위로 읽을 수 있습니다.

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);
}

이 답변은 선택한 답변과 거의 비슷하지만 두 가지 기능이 향상되었습니다. 즉, 메서드와 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();
        }
    }

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;
}

설명서는 이쪽입니다.

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 사용에 대한 훌륭한 튜토리얼입니다.

이것은 Brian RiskTry-with 스테이트먼트를 사용한 답변에 기초한 또 다른 Java 7 변형입니다.

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;
}

Apache를 사용하여 파일을 다운로드할 수 있습니다.HttpComponentsCommons 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많은 웹사이트에서 중요한 값입니다.

다음은 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);
    }

이전 답변을 요약(그리고 어떻게든 다듬고 업데이트)합니다.다음 세 가지 방법은 실질적으로 동일합니다.(필수라고 생각하기 때문에 명시적인 타임아웃을 추가했습니다.연결이 끊겼을 때 다운로드가 영원히 정지되는 것을 원하는 사람은 없습니다.)

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 directory 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 directory 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 directory 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();
}

저는 큰 차이를 찾을 수 없고, 모든 것이 맞는 것 같습니다.안전하고 효율적입니다.(속도 차이는 거의 관계가 없는 것 같습니다.로컬 서버에서 SSD 디스크로 180MB를 씁니다만, 약 1.2~1.5초의 변동 시간이 있습니다).외부 라이브러리는 필요 없습니다.모두 임의의 사이즈와 HTTP 리다이렉트 기능을 갖추고 있습니다.

추가로, 올스로우FileNotFoundException리소스를 찾을 수 없는 경우(일반적으로 오류 404),java.net.UnknownHostExceptionDNS 해결이 실패했을 경우, 다른 IOException은 전송 중 오류에 대응합니다.

방법이 있어요U.fetch(url), 언더스코어 포함 라이브러리로 이동합니다.

파일 pom.xml:

<dependency>
  <groupId>com.github.javadev</groupId>
  <artifactId>underscore</artifactId>
  <version>1.74</version>
</dependency>

코드 예:

import com.github.underscore.U;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Download {
    public static void main(String[] args) throws IOException {
        Files.write(Paths.get("data.bin"),
            U.fetch("https://stackoverflow.com/questions"
                + "/921262/how-to-download-and-save-a-file-from-internet-using-java").blob());
    }
}

Java 용 netloader 를 사용하면, 이것을 1 행으로 실행할 수 있습니다.

new NetFile(new File("my/zips/1.zip"), "https://example.com/example.zip", -1).load(); // Returns true if succeed, otherwise false.

이것은 인터넷에서 파일을 읽고 파일에 쓸 수 있다.

import java.net.URL;
import java.io.FileOutputStream;
import java.io.File;

public class Download {
    public static void main(String[] args) throws Exception {
         URL url = new URL("https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png");  // Input URL
         FileOutputStream out = new FileOutputStream(new File("out.png"));  // Output file
         out.write(url.openStream().readAllBytes());
         out.close();
    }
}

솔루션: java.net.2011.허가를 사용하는 Http Client:

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
        .GET()
        .header("Accept", "application/json")
        // .header("Authorization", "Basic ci5raG9kemhhZXY6NDdiYdfjlmNUM=") if you need
        .uri(URI.create("https://jira.google.ru/secure/attachment/234096/screenshot-1.png"))
        .build();

HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());

try (InputStream in = response.body()) {
    Files.copy(in, Paths.get(target + "screenshot-1.png"), StandardCopyOption.REPLACE_EXISTING);
}

다음의 간단한 사용법에 문제가 있습니다.

org.apache.commons.io.FileUtils.copyURLToFile(URL, File)

대용량 파일을 다운로드하여 저장해야 하는 경우 또는 연결이 끊긴 경우 자동 재시도가 필요한 경우 일반적으로 선택합니다.

이러한 경우 Apache Http Client와 org.apache.commons.io를 함께 사용하는 것이 좋습니다.파일유틸스예를 들어 다음과 같습니다.

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();
}

새로운 채널을 사용하는 첫 번째 방법

ReadableByteChannel aq = Channels.newChannel(new url("https//asd/abc.txt").openStream());
FileOutputStream fileOS = new FileOutputStream("C:Users/local/abc.txt")
FileChannel writech = fileOS.getChannel();

FileUtils를 사용하는 두 번째 방법

FileUtils.copyURLToFile(new url("https//asd/abc.txt", new local file on system("C":/Users/system/abc.txt"));

사용하는 세 번째 방법

InputStream xy = new ("https//asd/abc.txt").openStream();

기본 Java 코드 및 기타 서드파티 라이브러리를 사용하여 파일을 다운로드할 수 있습니다.이것들은 단지 빠른 참조를 위한 것입니다.자세한 정보 및 기타 옵션을 얻으려면 위의 키워드를 사용하여 구글을 검색하십시오.

프록시 뒤에 있는 경우 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("I/O exception");
        e.printStackTrace();
    }
    finally{
        if(outStream != null)
            outStream.close();
    }
}
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;
    }
}

언급URL : https://stackoverflow.com/questions/921262/how-can-i-download-and-save-a-file-from-the-internet-using-java

반응형