You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

从FTP服务器下载文件后损坏,请求分析相关代码问题

FTP下载文件损坏问题排查

嘿,我看了你的代码,马上发现几个会导致文件损坏的关键点,咱们一个个拆解:

  • buffer数据被覆盖,丢失大部分接收内容
    你现在每次调用recv(dataSocket, buffer, 30000, 0)时,新接收的数据会直接覆盖buffer里之前的内容。最后执行fout.write(buffer, size)的时候,你只把最后一次recv得到的那部分数据写入了文件,前面接收的所有字节都丢失了!这是文件损坏最直接的原因。
    解决办法是用一个动态容器来累积所有接收的数据,比如C++的vector<char>

    vector<char> receivedData;
    char buffer[30000];
    int iResult;
    int size = 0;
    do {
        iResult = recv(dataSocket, buffer, sizeof(buffer), 0);
        if (iResult > 0) {
            printf("Bytes received: %d\n", iResult);
            size += iResult;
            // 将本次接收的数据追加到容器末尾
            receivedData.insert(receivedData.end(), buffer, buffer + iResult);
        } else if (iResult == 0) {
            printf("Connection closed\n");
        } else {
            printf("recv failed: %d\n", WSAGetLastError());
            break; // 出错后终止循环,避免无效处理
        }
    } while (iResult > 0);
    cout << "the full size: " << size << endl;
    
    ofstream fout("test.png", ios_base::binary);
    fout.write(receivedData.data(), receivedData.size());
    fout.close(); // 确保数据全部写入磁盘
    
  • 未切换到FTP二进制传输模式
    FTP默认使用文本模式(TYPE A),如果传输png这类二进制文件,服务器会自动转换换行符(比如把\n转为\r\n),这会彻底破坏二进制文件的结构。你需要在发送RETR命令前,先发送TYPE I\r\n命令切换到二进制模式:

    // 先切换到二进制传输模式
    send(serverSocket, "TYPE I\r\n", strlen("TYPE I\r\n"), 0);
    // 再发送下载命令
    send(serverSocket, "RETR user.png\r\n", strlen("RETR user.png\r\n"), 0);
    
  • 额外的优化建议

    • 调用send时,用strlen()计算命令的字节数,代替硬写的15,避免命令长度变化导致发送不完整。
    • 写完文件后显式调用fout.close(),确保所有缓存的数据都刷新到磁盘,避免数据丢失。

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

火山引擎 最新活动