您的位置:

Java实现文件下载:从URL下载文件并保存至本地

一、URL下载文件


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

public class FileDownloader {
    public static void main(String[] args) throws Exception {
        String fileUrl = "https://example.com/file.pdf";
        URL url = new URL(fileUrl);
        BufferedInputStream bis = new BufferedInputStream(url.openStream());
        FileOutputStream fos = new FileOutputStream("/path/to/file.pdf");

        byte[] buffer = new byte[1024];
        int count = 0;

        while ((count = bis.read(buffer, 0, 1024)) != -1) {
            fos.write(buffer, 0, count);
        }

        fos.close();
        bis.close();
    }
}

在Java中下载文件的第一步是创建一个URL对象,用于指定文件的地址,然后创建一个BufferedInputStream对象,并将URL打开的流传递给它,从而获取文件数据。同时,创建一个FileOutputStream对象用于将从URL读取的数据保存在本地磁盘上。

然后,在while循环中,将从BufferedInputStream读取的数据写入FileOutputStream中,使用1024字节的缓冲区数组进行缓存,直至BufferedInputStream不再返回数据。最后,关闭流对象。

二、添加进度条


import java.net.URL;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;

import javax.swing.JProgressBar;

public class FileDownloadWithProgressBar extends Thread {
    private String fileUrl;
    private String savePath;
    private JProgressBar progressBar;

    public FileDownloadWithProgressBar(String fileUrl, String savePath, JProgressBar progressBar) {
        this.fileUrl = fileUrl;
        this.savePath = savePath;
        this.progressBar = progressBar;
    }

    public void run() {
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(fileUrl);
            bis = new BufferedInputStream(url.openStream());
            fos = new FileOutputStream(savePath);

            byte[] buffer = new byte[1024];
            int count = 0;
            int progress = 0;
            long fileSize = url.openConnection().getContentLength();

            while ((count = bis.read(buffer, 0, 1024)) != -1) {
                fos.write(buffer, 0, count);
                progress += count;
                int percentCompleted = (int) ((progress * 100) / fileSize);
                progressBar.setValue(percentCompleted);
                Thread.sleep(10);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

为了显示下载进度,我们可以通过创建一个带有进度条的GUI应用程序来实现,添加一个JProgressBar实例用来显示下载进度。在子线程中,循环读取数据,并在每次循环中更新进度条。

三、使用多线程下载


import java.net.URL;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;

public class MultiThreadFileDownload extends Thread {
    private String fileUrl;
    private String savePath;
    private long fileSize;

    private int startByte;
    private int endByte;

    public MultiThreadFileDownload(String fileUrl, String savePath, int startByte, int endByte) {
        this.fileUrl = fileUrl;
        this.savePath = savePath;
        this.startByte = startByte;
        this.endByte = endByte;
    }

    @Override
    public void run() {
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        try {
            URL url = new URL(fileUrl);
            bis = new BufferedInputStream(url.openStream());
            fos = new FileOutputStream(savePath);

            byte[] buffer = new byte[1024];

            long count = 0;
            int size = endByte - startByte + 1;

            bis.skip(startByte);

            while (count < size) {
                int len = bis.read(buffer, 0, 1024);
                if (len == -1) {
                    break;
                }
                fos.write(buffer, 0, len);
                count += len;
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

如果您需要加速下载过程,则可以使用多线程下载。每个线程将按照指定文件字节范围内的数据下载文件,并将其保存在本地磁盘上。然后,将所有线程下载的部分组合成完整的文件。使用多线程下载可以有效提高文件的下载速度。