Java文件下载案例如何实现

wen java案例 22

本文目录导读:

Java文件下载案例如何实现

  1. 基础HTTP文件下载(URL Connection)
  2. 断点续传下载
  3. 使用Apache HttpClient
  4. Web应用中的文件下载(Servlet)
  5. 多线程下载
  6. 异常处理与重试机制
  7. 完整的使用示例

我来详细讲解Java实现文件下载的几种常见方式。

基础HTTP文件下载(URL Connection)

简单文件下载

import java.io.*;
import java.net.*;
public class FileDownloader {
    public static void downloadFile(String fileURL, String savePath) throws IOException {
        URL url = new URL(fileURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置请求属性
        connection.setRequestMethod("GET");
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        // 获取输入流
        try (InputStream inputStream = connection.getInputStream();
             FileOutputStream outputStream = new FileOutputStream(savePath)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
        System.out.println("文件下载完成: " + savePath);
    }
    public static void main(String[] args) {
        try {
            downloadFile("https://example.com/file.pdf", "downloaded_file.pdf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

带进度条的下载

public class FileDownloadWithProgress {
    public static void downloadWithProgress(String fileURL, String savePath) throws IOException {
        URL url = new URL(fileURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 获取文件大小
        int fileSize = connection.getContentLength();
        System.out.println("文件大小: " + fileSize + " bytes");
        try (InputStream inputStream = connection.getInputStream();
             FileOutputStream outputStream = new FileOutputStream(savePath)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            int totalBytesRead = 0;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
                totalBytesRead += bytesRead;
                // 计算并显示进度
                if (fileSize > 0) {
                    int progress = (int) ((totalBytesRead * 100) / fileSize);
                    System.out.print("\r下载进度: " + progress + "%");
                }
            }
            System.out.println("\n下载完成!");
        }
    }
}

断点续传下载

public class ResumeDownload {
    public static void resumeDownload(String fileURL, String savePath) throws IOException {
        File file = new File(savePath);
        long existingFileSize = 0;
        // 检查是否已有部分下载的文件
        if (file.exists()) {
            existingFileSize = file.length();
            System.out.println("已有部分下载文件,大小: " + existingFileSize + " bytes");
        }
        URL url = new URL(fileURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置断点续传请求头
        if (existingFileSize > 0) {
            connection.setRequestProperty("Range", "bytes=" + existingFileSize + "-");
        }
        int responseCode = connection.getResponseCode();
        // 206表示部分内容,支持断点续传
        if (responseCode == HttpURLConnection.HTTP_PARTIAL || responseCode == HttpURLConnection.HTTP_OK) {
            try (InputStream inputStream = connection.getInputStream();
                 FileOutputStream outputStream = new FileOutputStream(savePath, true)) {
                byte[] buffer = new byte[4096];
                int bytesRead;
                long totalBytesRead = existingFileSize;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    totalBytesRead += bytesRead;
                    System.out.print("\r已下载: " + totalBytesRead + " bytes");
                }
                System.out.println("\n下载完成!");
            }
        }
    }
}

使用Apache HttpClient

import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.HttpEntity;
public class HttpClientDownload {
    public static void downloadWithHttpClient(String fileURL, String savePath) throws Exception {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpGet httpGet = new HttpGet(fileURL);
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    try (InputStream inputStream = entity.getContent();
                         FileOutputStream outputStream = new FileOutputStream(savePath)) {
                        byte[] buffer = new byte[4096];
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, bytesRead);
                        }
                    }
                }
            }
        }
        System.out.println("下载完成");
    }
}

Web应用中的文件下载(Servlet)

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
@WebServlet("/download")
public class FileDownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        String fileName = request.getParameter("file");
        String filePath = "/path/to/your/files/" + fileName;
        File file = new File(filePath);
        if (!file.exists()) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND);
            return;
        }
        // 设置响应头
        response.setContentType("application/octet-stream");
        response.setContentLength((int) file.length());
        response.setHeader("Content-Disposition", 
                          "attachment; filename=\"" + fileName + "\"");
        // 写入文件内容
        try (FileInputStream inputStream = new FileInputStream(file);
             OutputStream outputStream = response.getOutputStream()) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
    }
}

多线程下载

public class MultiThreadDownload {
    private static final int THREAD_COUNT = 4;
    public static void downloadWithMultiThread(String fileURL, String savePath) throws Exception {
        URL url = new URL(fileURL);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        int fileSize = connection.getContentLength();
        connection.disconnect();
        int partSize = fileSize / THREAD_COUNT;
        List<DownloadThread> threads = new ArrayList<>();
        // 创建并启动多个下载线程
        for (int i = 0; i < THREAD_COUNT; i++) {
            int start = i * partSize;
            int end = (i == THREAD_COUNT - 1) ? fileSize - 1 : (start + partSize - 1);
            DownloadThread thread = new DownloadThread(fileURL, savePath, start, end, i);
            threads.add(thread);
            thread.start();
        }
        // 等待所有线程完成
        for (DownloadThread thread : threads) {
            thread.join();
        }
        // 合并文件
        mergeFiles(savePath, THREAD_COUNT);
    }
    static class DownloadThread extends Thread {
        private String fileURL;
        private String savePath;
        private int start;
        private int end;
        private int threadId;
        public DownloadThread(String fileURL, String savePath, int start, int end, int threadId) {
            this.fileURL = fileURL;
            this.savePath = savePath;
            this.start = start;
            this.end = end;
            this.threadId = threadId;
        }
        @Override
        public void run() {
            try {
                URL url = new URL(fileURL);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestProperty("Range", "bytes=" + start + "-" + end);
                try (InputStream inputStream = connection.getInputStream();
                     RandomAccessFile outputFile = new RandomAccessFile(savePath + ".part" + threadId, "rw")) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputFile.write(buffer, 0, bytesRead);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private static void mergeFiles(String savePath, int threadCount) throws IOException {
        try (FileOutputStream outputStream = new FileOutputStream(savePath)) {
            for (int i = 0; i < threadCount; i++) {
                File partFile = new File(savePath + ".part" + i);
                try (FileInputStream inputStream = new FileInputStream(partFile)) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }
                partFile.delete();
            }
        }
    }
}

异常处理与重试机制

public class DownloadWithRetry {
    private static final int MAX_RETRIES = 3;
    private static final int RETRY_DELAY_MS = 2000;
    public static void downloadWithRetry(String fileURL, String savePath) {
        int retries = 0;
        boolean success = false;
        while (retries < MAX_RETRIES && !success) {
            try {
                downloadFile(fileURL, savePath);
                success = true;
                System.out.println("下载成功");
            } catch (IOException e) {
                retries++;
                System.err.println("下载失败 (尝试 " + retries + "/" + MAX_RETRIES + "): " + e.getMessage());
                if (retries < MAX_RETRIES) {
                    try {
                        Thread.sleep(RETRY_DELAY_MS);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
        }
        if (!success) {
            System.err.println("下载失败,已重试 " + MAX_RETRIES + " 次");
        }
    }
}

完整的使用示例

public class CompleteDownloadExample {
    public static void main(String[] args) {
        String fileURL = "https://example.com/large-file.zip";
        String savePath = "downloads/large-file.zip";
        // 创建下载目录
        new File("downloads").mkdirs();
        try {
            // 基础下载
            // FileDownloader.downloadFile(fileURL, savePath);
            // 带进度条下载
            // FileDownloadWithProgress.downloadWithProgress(fileURL, savePath);
            // 断点续传
            // ResumeDownload.resumeDownload(fileURL, savePath);
            // 多线程下载
            // MultiThreadDownload.downloadWithMultiThread(fileURL, savePath);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. 资源管理:使用 try-with-resources 自动关闭流
  2. 缓冲处理:使用缓冲区提高性能(4096 bytes 是常用值)
  3. 异常处理:处理网络超时、文件不存在等情况
  4. 编码问题:正确处理文件名编码
  5. 大文件处理:考虑使用断点续传或多线程下载
  6. 安全性:验证URL合法性,防止路径遍历攻击

选择哪种方式取决于你的具体需求,如文件大小、网络稳定性、是否需要断点续传等。

抱歉,评论功能暂时关闭!