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

客户端-服务器应用下载文件为空问题排查求助

客户端-服务器文件下载功能故障:生成空文件且未校验文件存在性

我正在开发一款客户端-服务器应用,实现文件下载功能时遇到问题:下载流程看似正常,文件会保存到两端指定的SAVE_DIRECTORY,但下载的文件始终为空,即便服务器上不存在该文件也会生成空文件。

服务端代码

elsif command.start_with?('download')
  filename = command[9..-1]
  client.puts("download #{filename}")  # Invia il comando per avviare il download
  save_path = File.join(SAVE_DIRECTORY, filename)
  if File.exist?(save_path)
    file_size = File.size(save_path)  # Ottieni la dimensione del file nel server
    client.puts(file_size.to_s)  # Invia la dimensione del file al client

    File.open(save_path, 'rb') do |file|
      client.write(file.read)  # Invia tutto il contenuto del file al client
    end
    puts "Download completato. Salvato come #{filename}".colorize(:green)
  else
    client.puts("Errore: Il file #{filename} non esiste.")
  end

客户端代码

elsif command.start_with?('download')
  client.puts(command)  
  filename = command[9..-1]  
  file_size = client.gets.to_i
  save_path = File.join(SAVE_DIRECTORY, filename)  
  file_size = client.gets.to_i  
  puts "Dimensione del file: #{file_size}".colorize(:yellow)

  File.open(save_path, 'wb') do |file|
    received_data = client.read(file_size)  
    file.write(received_data)
  end

  puts "Download completato. Salvato come #{filename}".colorize(:green)

我已完成的排查步骤:

  • 检查分块处理:确认两端数据读写、收发逻辑正确
  • 验证SAVE_DIRECTORY:确认路径配置正确
  • 检查文件存在性:服务端会先验证文件是否存在,不存在则返回错误
  • 调试输出:添加调试语句显示分块大小,结果符合预期
  • 文件读写检查:确认文件读写流程无误

修复方案与排查建议

问题根源分析

  1. 客户端重复读取文件大小:客户端连续两次调用client.gets.to_i,导致读取指针偏移,后续无法获取到实际文件内容,写入空文件。
  2. 未处理服务器错误响应:服务器返回错误字符串时,客户端仍尝试读取整数类型的文件大小(结果为0),进而创建空文件。
  3. 服务端冗余发送命令:服务端收到download命令后,又向客户端重复发送下载指令,造成交互逻辑混乱。

服务端代码修复

elsif command.start_with?('download')
  filename = command[9..-1]
  save_path = File.join(SAVE_DIRECTORY, filename)
  # 额外校验是文件而非目录,避免误处理
  if File.exist?(save_path) && File.file?(save_path)
    file_size = File.size(save_path)
    # 用固定前缀标识成功响应,方便客户端判断
    client.puts("SUCCESS #{file_size}")
    File.open(save_path, 'rb') do |file|
      # 分块发送大文件,避免内存溢出
      buffer = ''
      while file.read(4096, buffer)
        client.write(buffer)
      end
    end
    puts "Download completato. Salvato come #{filename}".colorize(:green)
  else
    client.puts("ERROR: Il file #{filename} non esiste o non è un file valido.")
  end

客户端代码修复

elsif command.start_with?('download')
  client.puts(command)  
  filename = command[9..-1]  
  # 读取服务器完整响应并去掉换行符
  response = client.gets.chomp
  save_path = File.join(SAVE_DIRECTORY, filename)  

  if response.start_with?('SUCCESS')
    file_size = response.split(' ')[1].to_i
    puts "Dimensione del file: #{file_size}".colorize(:yellow)
  
    File.open(save_path, 'wb') do |file|
      received = 0
      buffer = ''
      # 分块接收,确保完整读取所有内容
      while received < file_size
        chunk = client.read([4096, file_size - received].min)
        break unless chunk # 处理连接中断情况
        file.write(chunk)
        received += chunk.size
      end
    end
  
    puts "Download completato. Salvato come #{filename}".colorize(:green)
  else
    # 直接输出服务器错误,不创建空文件
    puts response.colorize(:red)
    return
  end

额外优化建议

  • 校验文件完整性:下载完成后,客户端可计算文件哈希值(如MD5/SHA),与服务器返回的哈希对比,确保文件未损坏。
  • 添加超时机制:在网络操作中设置超时,避免因网络卡顿导致程序挂起。
  • 日志记录:在关键步骤添加日志(如发送/接收字节数),方便后续排查问题。
  • 权限校验:服务端可添加文件权限检查,避免用户下载无权限访问的文件。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 20:59:59