จะดาวน์โหลดและบันทึกไฟล์จากอินเทอร์เน็ตโดยใช้ Java ได้อย่างไร


425

มีไฟล์ออนไลน์ (เช่นhttp://www.example.com/information.asp) ฉันต้องคว้าและบันทึกลงในไดเรกทอรี ฉันรู้ว่ามีหลายวิธีในการคว้าและอ่านไฟล์ออนไลน์ (URL) ทีละบรรทัด แต่มีวิธีดาวน์โหลดและบันทึกไฟล์โดยใช้ Java หรือไม่


คำตอบ:


559

ให้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 ไบต์ (ใหญ่กว่าไฟล์ใด ๆ ที่มีอยู่)


22
ปิดทั้งสามด้วย Java 7 try-with-resource: ลอง (InputStream inputStream = website.openStream (); ReadableByteChannel readableByteChannel = Channels.newChannel (inputStream); FileOutputStream = FileOutputStream ใหม่ (อ่านได้โดยช่องสัญญาณ, 0, 1 << 24); }
mazatwork

80
นี้จะดาวน์โหลด 16MB แรกของไฟล์: stackoverflow.com/questions/8405062/downloading-files-with-java
เบน McCann

31
@ kirdie และถ้าฉันต้องการมากกว่า8388608TB?
Cruncher

22
การโทรครั้งเดียวไม่เพียงพอ transferFrom()isnt 'ระบุไว้เพื่อให้การถ่ายโอนทั้งหมดเสร็จสมบูรณ์ในการโทรครั้งเดียว นั่นเป็นเหตุผลที่มันกลับมานับ คุณต้องห่วง
มาร์ควิสแห่ง Lorne

11
ทำไมคำตอบนี้ถึงได้รับการยอมรับ URL::openStream()ส่งคืนเฉพาะสตรีมปกติหมายความว่าปริมาณการใช้ข้อมูลทั้งหมดยังคงถูกคัดลอกผ่านอาร์เรย์ Java byte [] แทนที่จะเหลืออยู่ในบัฟเฟอร์ดั้งเดิม เพียงfos.getChannel()เป็นจริงช่องพื้นเมืองจึงยังคงค่าใช้จ่ายในราคาเต็ม นั่นคือไม่มีกำไรจากการใช้ NIO ในกรณีนี้ นอกเหนือจากการถูกทำลายเนื่องจาก EJP และ Ben MacCann สังเกตเห็นได้อย่างถูกต้อง
Ext3h

494

ใช้ apache commons-ioเพียงหนึ่งบรรทัดโค้ด:

FileUtils.copyURLToFile(URL, File)

22
ดี! สิ่งที่ฉันกำลังมองหา! ฉันรู้ว่าห้องสมุด Apache จะครอบคลุมเรื่องนี้อยู่แล้ว BTW ขอแนะนำให้ใช้เวอร์ชันที่มีการโหลดมากเกินไปพร้อมพารามิเตอร์การหมดเวลา!
Hendy Irawan

6
... และเมื่อใช้เวอร์ชันที่มีการใช้งานมากเกินไปโปรดจำไว้ว่าการหมดเวลาใช้งานจะระบุเป็นมิลลิวินาทีไม่ใช่วินาที
László van den Hoek

5
โปรดทราบว่าcopyURLToFileด้วยพารามิเตอร์การหมดเวลาใช้งานได้ตั้งแต่ไลบรารี่ Commons IO เวอร์ชัน 2.0 เท่านั้น ดูเอกสาร Java
สแตนลีย์

6
จะทำอย่างไรถ้าต้องเพิ่มส่วนหัวการรับรองความถูกต้องเบื้องต้นลงในคำขอ มีวิธีแก้ปัญหาหรือไม่?
เมียน

3
แม้ว่านี่จะเป็น "สั้น" แต่จริงๆแล้วช้ามาก
Meinkraft

123

การใช้ nio ง่ายขึ้น:

URL website = new URL("http://www.website.com/information.asp");
try (InputStream in = website.openStream()) {
    Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
}

5
น่าเสียดายที่นี่ไม่ทำงานแบบเงียบ ๆ (ดาวน์โหลด 0 ไบต์) ในกรณีที่มีการเปลี่ยนเส้นทางเช่น "302 Found"
Alexander K

1
@AlexanderK แต่ทำไมคุณต้องดาวน์โหลดทรัพยากรแบบนี้ต่อไป?
xuesheng

5
แม้จะมีความจริงที่ว่านี่เป็นวิธีการแก้ปัญหาที่สง่างาม แต่เบื้องหลังวิธีการนี้อาจทำให้คุณทรยศ Files.copy (InputStream, Paths, FileOption) มอบหมายกระบวนการคัดลอกให้กับ Files.copy (InputStream, OutputStream) วิธีสุดท้ายนี้ไม่ได้ตรวจสอบการสิ้นสุดของสตรีม (-1) แต่จะตรวจสอบว่าไม่มีการอ่านไบต์ (0) หมายความว่าหากเครือข่ายของคุณมีการหยุดชั่วคราวเล็กน้อยสามารถอ่านได้ 0 ไบต์และสิ้นสุดกระบวนการคัดลอกแม้ว่าระบบปฏิบัติการจะไม่สามารถดาวน์โหลดสตรีมได้
Miere

6
@Miere เป็นไปไม่ได้ที่InputStream.read()จะคืนค่าศูนย์เว้นแต่คุณจะให้บัฟเฟอร์ความยาวเป็นศูนย์หรือนับเป็น 'หยุดชั่วคราว' หรืออย่างอื่น มันจะบล็อกจนกว่าจะมีการถ่ายโอนอย่างน้อยหนึ่งไบต์หรือสิ้นสุดสตรีมหรือมีข้อผิดพลาดเกิดขึ้น การเรียกร้องของคุณเกี่ยวกับภายในของFiles.copy()ไม่มีมูลความจริง
มาร์ควิสแห่ง Lorne

3
ฉันมีการทดสอบหน่วยที่อ่านไฟล์ไบนารีด้วย 2.6TiB การใช้ Files.copy จะล้มเหลวบนเซิร์ฟเวอร์ที่เก็บข้อมูล HDD (XFS) ของฉันเสมอ แต่จะล้มเหลวเพียงสองสามเท่าของ SSH ของฉัน ดูที่ JDK 8 รหัสของ File.copy ฉันได้ระบุว่ามันจะตรวจสอบ '> 0' เพื่อออกจากลูป 'while' ฉันเพิ่งคัดลอกรหัสเดียวกันกับ -1 และการทดสอบหน่วยทั้งไม่เคยหยุดอีกครั้ง เมื่อ InputStream สามารถเป็นตัวแทนของเครือข่ายและตัวอธิบายไฟล์ในระบบและการดำเนินการ IO ทั้งสองอยู่ภายใต้การสลับบริบทของระบบปฏิบัติการฉันไม่เห็นเหตุผลที่การอ้างสิทธิ์ของฉันไม่มีมูลความจริง บางคนอาจอ้างว่ามันทำงานได้ด้วยโชค แต่มันไม่ทำให้ปวดหัวอีกต่อไป
Miere

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

คุณจะต้องจัดการกับข้อยกเว้นซึ่งอาจเป็นวิธีภายนอก


6
วิธีดาวน์โหลดเร็วขึ้นมาก? ชอบตัวเร่งความเร็วในการดาวน์โหลด?
digz6666

11
หากin.closeโยนข้อยกเว้นfout.closeจะไม่ถูกเรียก
เบริลเลียม

1
@ComFreek นั่นเป็นเรื่องจริง การใช้ a BufferedInputStreamมีผลเป็นศูนย์อย่างแม่นยำกับการหมดเวลาซ็อกเก็ต ฉันได้ปฏิเสธแล้วว่าเป็น 'ตำนานเมือง' ในความคิดเห็นของฉันต่อ 'รายละเอียดพื้นหลัง' ที่คุณอ้างถึง เมื่อสามปีก่อน
มาร์ควิสแห่ง Lorne

@EJP ขอบคุณสำหรับการแก้ไข! ฉันลบความคิดเห็นของฉัน (สำหรับที่เก็บถาวร: ฉันเชื่อมโยงกับคำตอบนี้โดยระบุว่าBufferedInputStream"อาจทำให้เกิดความล้มเหลวที่คาดเดาไม่ได้")
ComFreek

+1 ข้อคัดค้านของฉันสำหรับคำตอบนี้ (และอื่น ๆ ที่นี่) คือผู้โทรไม่สามารถแยกแยะเหตุการณ์ "ไม่พบ" จากข้อผิดพลาดการเชื่อมต่อบางอย่าง (ซึ่งคุณอาจต้องการลองใหม่)
leonbloy

24

เป็นคำถามเก่า แต่ที่นี่เป็นโซลูชัน 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));
    }
}

โค้ดสองบรรทัดและไม่มีการขึ้นต่อกัน


สำหรับผู้ที่กำลังสงสัยนี่คือการนำเข้าที่จำเป็นสำหรับตัวอย่างของรหัสนี้:import java.io.InputStream; import java.net.URI; import java.nio.file.Files; import java.nio.file.Paths;
BelovedFool

23

การดาวน์โหลดไฟล์คุณจะต้องอ่านไฟล์ไม่ว่าจะด้วยวิธีการใดก็ตาม แทนที่จะอ่านทีละบรรทัดคุณสามารถอ่านทีละไบต์จากสตรีม:

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

17

เมื่อใช้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;
}

เอกสารที่นี่


16

คำตอบนี้เหมือนกับคำตอบที่เลือก แต่มีการปรับปรุงสองอย่าง: เป็นวิธีการและปิดวัตถุ 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();
        }
    }

2
การโทรครั้งเดียวไม่เพียงพอ transferFrom()isnt 'ระบุไว้เพื่อให้การถ่ายโอนทั้งหมดเสร็จสมบูรณ์ในการโทรครั้งเดียว นั่นเป็นเหตุผลที่มันกลับมานับ คุณต้องห่วง
มาร์ควิสแห่ง Lorne

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

5
หากin.closeโยนข้อยกเว้นout.closeจะไม่ถูกเรียก
เบริลเลียม

8

โดยส่วนตัวแล้วฉันได้พบHttpClient ของ Apacheมีความสามารถมากกว่าทุกอย่างที่ฉันต้องการเกี่ยวกับเรื่องนี้ นี่คือการสอนที่ยอดเยี่ยมเกี่ยวกับการใช้ HttpClient


2
ยังคอมมอน-io เป็นห้องสมุดที่ดี
DFA

6

นี่คือตัวแปร java7 อีกตัวหนึ่งซึ่งอิงจากคำตอบของ Brian Riskกับการใช้คำสั่ง 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 'ระบุไว้เพื่อให้การถ่ายโอนทั้งหมดเสร็จสมบูรณ์ในการโทรครั้งเดียว นั่นเป็นเหตุผลที่มันกลับมานับ คุณต้องห่วง
มาร์ควิสแห่ง Lorne

ฉันไม่รู้ว่าทำไมคุณตอบคำถามโง่ ๆ มาให้ฉัน มันไม่มีอะไรเกี่ยวข้องกับสิ่งที่ฉันพูดและฉันก็ปฏิเสธที่จะใส่คำเข้าไปในปากของฉัน
มาร์ควิสแห่ง Lorne

2

มันเป็นไปได้ที่จะดาวน์โหลดไฟล์ที่มีกับ 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ค่านิยมซึ่งมีความสำคัญสำหรับเว็บไซต์หลายแห่ง


2

มีคำตอบที่หรูหราและมีประสิทธิภาพมากมายที่นี่ แต่ความรัดกุมสามารถทำให้เราสูญเสียข้อมูลที่เป็นประโยชน์บางอย่าง โดยเฉพาะอย่างยิ่งมักจะไม่ต้องการพิจารณาข้อผิดพลาดการเชื่อมต่อข้อยกเว้นและหนึ่งอาจต้องการจัดการข้อผิดพลาดที่เกี่ยวข้องกับเครือข่ายบางประเภทแตกต่างกัน - ตัวอย่างเช่นการตัดสินใจว่าเราควรลองดาวน์โหลดอีกครั้ง

ต่อไปนี้เป็นวิธีการที่ไม่ทิ้งข้อยกเว้นสำหรับข้อผิดพลาดของเครือข่าย (เฉพาะปัญหาที่ยอดเยี่ยมอย่างแท้จริงเช่น 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;
}

2

ด้านล่างเป็นตัวอย่างโค้ดสำหรับดาวน์โหลดภาพยนตร์จากอินเทอร์เน็ตด้วยรหัส 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);
    }

โดยทั่วไปแล้วคำตอบมีประโยชน์มากขึ้นหากพวกเขามีคำอธิบายว่ารหัสนี้มีจุดประสงค์เพื่ออะไรและเหตุใดจึงแก้ปัญหาได้โดยไม่ต้องแนะนำผู้อื่น
Tim Diekmann

1

มีปัญหากับการใช้งานที่ง่ายของ:

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

1

เพื่อสรุป (และขัดและปรับปรุง) คำตอบก่อนหน้า วิธีการทั้งสามต่อไปนี้เทียบเท่ากันในทางปฏิบัติ (ฉันเพิ่มการหมดเวลาอย่างชัดเจนเพราะฉันคิดว่าพวกเขาเป็นสิ่งจำเป็นไม่มีใครต้องการการดาวน์โหลดเพื่อหยุดตลอดไปเมื่อการเชื่อมต่อขาดหายไป)

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

ฉันไม่พบความแตกต่างอย่างมีนัยสำคัญทุกอย่างดูเหมือนถูกต้องสำหรับฉัน พวกเขาปลอดภัยและมีประสิทธิภาพ (ความแตกต่างของความเร็วดูไม่เกี่ยวข้องเลย - ฉันเขียน 180Mb จากเซิร์ฟเวอร์ภายในเครื่องไปยังดิสก์ SSD ในเวลาที่ผันผวนประมาณ 1.2 ถึง 1.5 segs) พวกเขาไม่ต้องการห้องสมุดภายนอก ทั้งหมดทำงานกับขนาดโดยพลการและการเปลี่ยนเส้นทาง HTTP (เป็นประสบการณ์ของฉัน)

นอกจากนี้การโยนทั้งหมดFileNotFoundExceptionหากไม่พบทรัพยากร (ข้อผิดพลาด 404 โดยทั่วไป) และjava.net.UnknownHostExceptionหากการแก้ไข DNS ล้มเหลว IOException อื่น ๆ สอดคล้องกับข้อผิดพลาดระหว่างการส่งข้อมูล

(ทำเครื่องหมายว่าเป็นชุมชน wiki โปรดเพิ่มข้อมูลหรือแก้ไข)


1

มีเมธอด 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();
    }
}

คำตอบนี้มีประโยชน์อย่างไรเมื่อลิงก์ไม่ถูกต้อง โปรดดูวิธีการตอบ
JimHawkins

รหัสของคุณจะไม่รวบรวม คำถามถามหาทางแก้ไขJavaแต่คำตอบของคุณดูเหมือนJavaScript
talex

@talex ฉันเพิ่มส่วน pom.xml และตัวอย่างโค้ดที่ได้รับการปรับปรุง
Valentyn Kolesnikov

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

คุณสามารถปรับปรุงคำตอบของคุณโดยการให้ข้อมูลว่าโค้ดทำงานอย่างไรแทนที่จะทิ้งไว้
Matej Kormuth


0

หากคุณอยู่หลังพร็อกซีคุณสามารถตั้งค่าพรอกซีในโปรแกรมจาวาได้ดังต่อไปนี้:

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

0

วิธีที่ 1 โดยใช้ช่องทางใหม่

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

วิธีที่ 2 โดยใช้ FileUtils

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

วิธีที่ 3 โดยใช้

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

นี่คือวิธีที่เราสามารถดาวน์โหลดไฟล์โดยใช้รหัส java พื้นฐานและห้องสมุดบุคคลที่สามอื่น ๆ เหล่านี้เป็นเพียงสำหรับการอ้างอิงอย่างรวดเร็ว โปรด google ด้วยคำหลักข้างต้นเพื่อรับข้อมูลโดยละเอียดและตัวเลือกอื่น ๆ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.