客户端-服务器应用下载文件为空问题排查求助
客户端-服务器文件下载功能故障:生成空文件且未校验文件存在性
我正在开发一款客户端-服务器应用,实现文件下载功能时遇到问题:下载流程看似正常,文件会保存到两端指定的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:确认路径配置正确 - 检查文件存在性:服务端会先验证文件是否存在,不存在则返回错误
- 调试输出:添加调试语句显示分块大小,结果符合预期
- 文件读写检查:确认文件读写流程无误
修复方案与排查建议
问题根源分析
- 客户端重复读取文件大小:客户端连续两次调用
client.gets.to_i,导致读取指针偏移,后续无法获取到实际文件内容,写入空文件。 - 未处理服务器错误响应:服务器返回错误字符串时,客户端仍尝试读取整数类型的文件大小(结果为0),进而创建空文件。
- 服务端冗余发送命令:服务端收到
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
相关产品推荐
相关产品推荐

