如何在Java NIO中下载图片后校验文件长度与Content-Length匹配?
实现WebP下载后的Content-Length校验方案
原代码使用transferFrom时可能出现文件未完全下载的情况,要校验本地文件长度与响应头的Content-Length是否一致,你需要改用HttpURLConnection来发起请求(URL.openStream()无法获取响应头信息),具体实现步骤如下:
修改后的完整代码
import java.io.FileOutputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; static void downloadWebp(String url) { URL urlObj; try { urlObj = new URL(url); } catch (MalformedURLException e) { throw new RuntimeException("无效的URL格式", e); } HttpURLConnection connection = null; ReadableByteChannel readableByteChannel = null; Path savePath = Paths.get(System.getProperty("user.home"), "image", Paths.get(urlObj.getPath()).getFileName().toString()); try { // 打开HTTP连接并获取响应头 connection = (HttpURLConnection) urlObj.openConnection(); connection.setRequestMethod("GET"); connection.connect(); // 获取响应头中的Content-Length long expectedLength = connection.getContentLengthLong(); if (expectedLength == -1) { throw new RuntimeException("响应头未返回Content-Length,无法校验"); } // 开始下载文件 readableByteChannel = Channels.newChannel(connection.getInputStream()); try (FileOutputStream fileOutputStream = new FileOutputStream(savePath.toAbsolutePath().toString())) { fileOutputStream.getChannel().transferFrom(readableByteChannel, 0, Long.MAX_VALUE); } // 校验本地文件长度与Content-Length是否一致 long actualLength = Files.size(savePath); if (actualLength != expectedLength) { // 可根据需求调整逻辑:删除不完整文件、重试下载等 Files.deleteIfExists(savePath); throw new RuntimeException(String.format("文件下载不完整:预期%d字节,实际%d字节", expectedLength, actualLength)); } } catch (IOException e) { // 异常时清理不完整文件 try { Files.deleteIfExists(savePath); } catch (IOException ex) { ex.printStackTrace(); } throw new RuntimeException("下载或校验失败", e); } finally { // 关闭资源 if (connection != null) { connection.disconnect(); } if (readableByteChannel != null) { try { readableByteChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } }
关键改动说明
- 改用
HttpURLConnection发起请求,通过getContentLengthLong()获取响应头中的文件预期长度(支持大文件场景) - 下载完成后调用
Files.size(savePath)获取本地文件实际大小 - 对比预期与实际长度,不一致时自动删除无效文件并抛出异常(可自行扩展为重试下载逻辑)
- 补充了资源关闭与异常清理逻辑,避免残留无效文件
调用示例
downloadWebp("https://cdn.discordapp.com/attachments/1098794840742961242/1100590092957003877/Jeffery_cherry_blossoms_blooming_in_the_rain_by_Yoko_Ishii_wate_8a2f060e-32dc-4567-a3df-8bfdbb56adfd.webp");
内容的提问来源于stack exchange,提问作者djy
相关产品推荐
相关产品推荐

