You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Socket文件传输不完整问题求助:文件损坏或大小不符

问题分析与解决方案

核心问题

你的文件传输不稳定、文件损坏的原因有两个:

  1. 服务器无法判断传输结束:Socket输入流的read()方法返回-1的前提是对方关闭了输出流或Socket连接。客户端仅调用flush()但未告知服务器传输结束,导致服务器的while循环会一直阻塞在read(),直到客户端Socket意外关闭,此时可能还有部分数据未被完整读取,造成文件截断。
  2. 服务器代码存在语法错误:try-with-resources语句后缺少大括号,BufferedInputStream downloader未被纳入资源管理,可能导致资源泄漏或数据缓冲未及时写入文件。

修复方案

方案一:通过关闭输出流标记传输结束

这种方式简单直接,适合不需要复用Socket的场景:

修改客户端uploadFile方法:
在flush()后调用socket.shutdownOutput(),明确告知服务器没有更多数据传输:

public void uploadFile(Socket socket, String path) {
    try (BufferedInputStream file = new BufferedInputStream(new FileInputStream(path));
         BufferedOutputStream uploader = new BufferedOutputStream(socket.getOutputStream())) {
        byte[] bytes = new byte[1024];
        int count;
        while ((count = file.read(bytes)) != -1)
            uploader.write(bytes, 0, count);
        uploader.flush();
        socket.shutdownOutput(); // 发送结束标记,服务器read()会返回-1
    } catch (Exception e) {
        e.printStackTrace();
    }
}

修复服务器downloadFile方法的语法错误:
将BufferedInputStream纳入try-with-resources管理,确保资源正确释放:

public void downloadFile(Socket socket, String path) {
    try (BufferedOutputStream file = new BufferedOutputStream(new FileOutputStream(path));
         BufferedInputStream downloader = new BufferedInputStream(socket.getInputStream())) {
        byte[] bytes = new byte[1024];
        int count;
        while ((count = downloader.read(bytes)) != -1)
            file.write(bytes, 0, count);
        file.flush(); // 确保缓冲数据写入文件
    } catch (IOException e) {
        System.out.println("Respounder.downloadFile("+path+"): IOException");
        e.printStackTrace();
    }
}

方案二:先传输文件长度(更可靠,支持Socket复用)

如果需要后续复用Socket进行其他通信,建议先发送文件总长度,服务器根据长度精确读取数据,无需依赖流关闭:

客户端修改:
使用DataOutputStream先发送文件长度,再传输文件内容:

public void uploadFile(Socket socket, String path) {
    try (BufferedInputStream file = new BufferedInputStream(new FileInputStream(path));
         DataOutputStream uploader = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()))) {
        File targetFile = new File(path);
        uploader.writeLong(targetFile.length()); // 先发送文件总字节数
        byte[] bytes = new byte[1024];
        int count;
        while ((count = file.read(bytes)) != -1)
            uploader.write(bytes, 0, count);
        uploader.flush();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

服务器修改:
使用DataInputStream先读取文件长度,再循环读取对应字节数:

public void downloadFile(Socket socket, String path) {
    try (BufferedOutputStream file = new BufferedOutputStream(new FileOutputStream(path));
         DataInputStream downloader = new DataInputStream(new BufferedInputStream(socket.getInputStream()))) {
        long totalBytes = downloader.readLong(); // 获取文件总长度
        byte[] bytes = new byte[1024];
        long receivedBytes = 0;
        int count;
        // 精确读取到指定字节数后停止
        while (receivedBytes < totalBytes && 
               (count = downloader.read(bytes, 0, (int) Math.min(bytes.length, totalBytes - receivedBytes))) != -1) {
            file.write(bytes, 0, count);
            receivedBytes += count;
        }
        file.flush();
    } catch (IOException e) {
        System.out.println("Respounder.downloadFile("+path+"): IOException");
        e.printStackTrace();
    }
}

内容的提问来源于stack exchange,提问作者hansoko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:05:01