Java环境下MP3文件下载不完整问题求助
问题:提取MP3下载链接后,仅能下载1.13MB文件即中断
我需要通过下述API获取MP3下载链接并完成下载:
https://api.vevioz.com/@api/button/mp3/AKX91G0qNFM
我用Jsoup解析页面提取下载URL,但无论用Java IO、NIO、AsyncHttpClient还是Apache Commons IO方式下载,都只能得到1.13MB的文件,之后程序就会退出,找不到解决办法。
我的代码如下:
Jsoup 提取链接代码
Document doc = Jsoup.connect("https://api.vevioz.com/@api/button/mp3/AKX91G0qNFM").get(); Element body=doc.body(); Elements elements=body.getElementsByClass("download flex flex-wrap sm:inline-flex text-center items-center justify-center"); elements=elements.get(0).children(); String FILE_URL=elements.get(0).attributes().get("href"); String FILE_NAME="./downloads/1.mp3";
Java IO 下载代码
try (BufferedInputStream in = new BufferedInputStream(new URL(FILE_URL).openStream()); FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME)) { byte[] dataBuffer = new byte[1024]; int bytesRead; while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) { fileOutputStream.write(dataBuffer, 0, bytesRead); } } catch (IOException e) { // handle exception }
NIO 下载代码
ReadableByteChannel readableByteChannel = Channels.newChannel(new URL(FILE_URL).openStream()); FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME); FileChannel fileChannel = fileOutputStream.getChannel(); fileOutputStream.getChannel() .transferFrom(readableByteChannel, 0, Long.MAX_VALUE);
AsyncHttpClient 下载代码
AsyncHttpClient client = Dsl.asyncHttpClient(); FileOutputStream stream = new FileOutputStream(FILE_NAME); client.prepareGet(link).execute(new AsyncCompletionHandler<FileOutputStream>() { @Override public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { stream.getChannel().write(bodyPart.getBodyByteBuffer()); return State.CONTINUE; } @Override public FileOutputStream onCompleted(org.asynchttpclient.Response response) throws Exception { return stream; } });
Apache Commons IO 下载代码
FileUtils.copyURLToFile(new URL(FILE_URL),new File(FILE_NAME));
可能的原因及解决方案
1. 服务器拦截无请求头的下载请求
多数文件托管服务会校验请求的User-Agent和Referer字段,拒绝非浏览器发起的直接下载请求,导致仅返回部分数据就断开连接。
解决办法:添加模拟浏览器的请求头
- Java IO 方式修改:
URL url = new URL(FILE_URL); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // 模拟Chrome浏览器请求头 connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"); // 添加来源页Referer connection.setRequestProperty("Referer", "https://api.vevioz.com/@api/button/mp3/AKX91G0qNFM"); // 开启重定向跟随 connection.setInstanceFollowRedirects(true); try (BufferedInputStream in = new BufferedInputStream(connection.getInputStream()); FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME)) { byte[] dataBuffer = new byte[4096]; // 增大缓冲区提升下载效率 int bytesRead; while ((bytesRead = in.read(dataBuffer, 0, 4096)) != -1) { fileOutputStream.write(dataBuffer, 0, bytesRead); } } catch (IOException e) { e.printStackTrace(); }
- NIO 方式修改:
URL url = new URL(FILE_URL); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"); connection.setRequestProperty("Referer", "https://api.vevioz.com/@api/button/mp3/AKX91G0qNFM"); try (ReadableByteChannel readableByteChannel = Channels.newChannel(connection.getInputStream()); FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME); FileChannel fileChannel = fileOutputStream.getChannel()) { fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE); } catch (IOException e) { e.printStackTrace(); }
- AsyncHttpClient 方式修改:
AsyncHttpClient client = Dsl.asyncHttpClient(); FileOutputStream stream = new FileOutputStream(FILE_NAME); client.prepareGet(FILE_URL) .setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") .setHeader("Referer", "https://api.vevioz.com/@api/button/mp3/AKX91G0qNFM") .execute(new AsyncCompletionHandler<FileOutputStream>() { @Override public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { stream.getChannel().write(bodyPart.getBodyByteBuffer()); return State.CONTINUE; } @Override public FileOutputStream onCompleted(org.asynchttpclient.Response response) throws Exception { stream.close(); // 必须显式关闭流 return stream; } @Override public void onThrowable(Throwable t) { try { stream.close(); } catch (IOException e) { e.printStackTrace(); } t.printStackTrace(); } });
2. 流未正确关闭导致文件截断
部分代码未用try-with-resources包裹流,或未在完成/异常时关闭输出流,导致文件未完全写入就被截断。确保所有流都通过try-with-resources自动管理,或在finally块中手动关闭。
3. 未正确跟随重定向
部分下载链接是临时跳转地址,需确保请求开启重定向跟随。HttpURLConnection默认开启,但显式设置connection.setInstanceFollowRedirects(true)更稳妥。
内容的提问来源于stack exchange,提问作者Yavar007
相关产品推荐
相关产品推荐

