package com.estate.expert.admin.utils; import java.io.*; import java.net.*; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.Map; import java.util.HashMap; public class FileDownloader { /** * 增强的文件下载方法 */ public byte[] downloadFile(String fileUrl) throws Exception { // 验证URL if (fileUrl == null || fileUrl.trim().isEmpty()) { throw new IllegalArgumentException("URL不能为空"); } URL url = new URL(fileUrl); // 设置超时和请求头 HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"); connection.setRequestProperty("Accept", "application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/msword"); connection.setConnectTimeout(30000); connection.setReadTimeout(60000); connection.setInstanceFollowRedirects(true); int responseCode = connection.getResponseCode(); if (responseCode != HttpURLConnection.HTTP_OK) { throw new IOException("HTTP请求失败,状态码: " + responseCode); } // 检查内容类型 String contentType = connection.getContentType(); if (contentType == null || (!contentType.contains("word") && !contentType.contains("octet-stream") && !contentType.contains("document"))) { System.out.println("警告: 内容类型可能不是Word文档: " + contentType); } // 获取文件大小 int contentLength = connection.getContentLength(); System.out.println("文件大小: " + (contentLength > 0 ? contentLength + " 字节" : "未知")); // 下载文件 try (InputStream inputStream = connection.getInputStream(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { byte[] buffer = new byte[8192]; int bytesRead; long totalBytes = 0; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); totalBytes += bytesRead; if (contentLength > 0) { int progress = (int) ((totalBytes * 100) / contentLength); if (progress % 10 == 0) { System.out.print("\r下载进度: " + progress + "%"); } } } byte[] fileData = outputStream.toByteArray(); if (fileData.length == 0) { throw new IOException("下载的文件内容为空"); } System.out.println("\n下载完成,实际大小: " + fileData.length + " 字节"); // 验证文件格式(检查是否是有效的Word文档) if (!isValidWordDocument(fileData)) { System.out.println("警告: 下载的文件可能不是有效的Word文档"); } return fileData; } finally { connection.disconnect(); } } /** * 验证是否为有效的Word文档 */ private boolean isValidWordDocument(byte[] data) { if (data.length < 4) { return false; } // 检查.docx格式 (ZIP格式) if (data[0] == 0x50 && data[1] == 0x4B && data[2] == 0x03 && data[3] == 0x04) { return true; } // 检查.doc格式 (OLE格式) if (data[0] == (byte)0xD0 && data[1] == (byte)0xCF && data[2] == 0x11 && data[3] == (byte)0xE0) { return true; } return false; } /** * 下载并保存到文件 */ public File downloadToFile(String fileUrl, String outputPath) throws Exception { byte[] data = downloadFile(fileUrl); File outputFile = new File(outputPath); File parentDir = outputFile.getParentFile(); if (parentDir != null && !parentDir.exists()) { parentDir.mkdirs(); } try (FileOutputStream fos = new FileOutputStream(outputFile)) { fos.write(data); } System.out.println("文件已保存到: " + outputFile.getAbsolutePath()); return outputFile; } /** * 批量下载 */ public Map batchDownload(String[] urls) { Map results = new HashMap<>(); for (String url : urls) { try { System.out.println("下载: " + url); byte[] data = downloadFile(url); results.put(url, data); System.out.println("✓ 下载成功"); } catch (Exception e) { System.err.println("✗ 下载失败: " + e.getMessage()); results.put(url, null); } } return results; } /** * 使用NIO下载(更高效) */ public void downloadWithNIO(String fileUrl, String outputPath) throws Exception { URL url = new URL(fileUrl); try (InputStream inputStream = url.openStream(); ReadableByteChannel rbc = Channels.newChannel(inputStream); FileOutputStream fos = new FileOutputStream(outputPath)) { fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); } System.out.println("NIO下载完成: " + outputPath); } }