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

使用Faraday::UploadIO调用Telegram API后无法移动文件的问题

问题解决:Faraday::UploadIO文件占用导致无法移动文件

核心原因

Faraday::UploadIO创建时会打开文件句柄,默认情况下句柄会在请求完成后由Ruby垃圾回收机制自动释放,但如果网络请求延迟或垃圾回收未及时触发,文件会处于被占用状态,导致FileUtils.mv执行时出现权限拒绝错误。

解决方法

1. 显式关闭UploadIO的文件句柄

把UploadIO实例保存到变量,发送完Telegram请求后手动关闭内部文件对象,确保句柄被释放:

Dir.glob("*.{jpg,png}").each do |file|
  # ... 省略图片检查、压缩逻辑 ...

  # 发送照片并关闭句柄
  if file.match?(/[0-9]_p[0-9]\.(jpg|png)/)
    photo_upload = Faraday::UploadIO.new(check_image, exten)
    bot.api.send_photo(
      chat_id: channel_id,
      photo: photo_upload,
      parse_mode:"MarkdownV2",
      caption: "[Source pixiv](https://www.pixiv.net/en/artworks/#{file[..file.index("_p")-1]})"
    )
    photo_upload.file.close
  else
    photo_upload = Faraday::UploadIO.new(check_image, exten)
    bot.api.send_photo(
      chat_id: channel_id,
      photo: photo_upload
    )
    photo_upload.file.close
  end

  # 发送文档并关闭句柄
  doc_upload = Faraday::UploadIO.new(file, exten)
  bot.api.send_document(chat_id:channel_id, document: doc_upload)
  doc_upload.file.close

  # 安全移动文件
  FileUtils.mv(file, File.join("uploaded", file))
end

2. 使用File.open块自动管理文件句柄

通过File.open的块形式打开文件,块执行完毕后会自动关闭句柄,再传递给UploadIO:

Dir.glob("*.{jpg,png}").each do |file|
  # ... 省略图片检查、压缩逻辑 ...

  # 发送照片
  if file.match?(/[0-9]_p[0-9]\.(jpg|png)/)
    File.open(check_image, 'rb') do |f|
      bot.api.send_photo(
        chat_id: channel_id,
        photo: Faraday::UploadIO.new(f, exten),
        parse_mode:"MarkdownV2",
        caption: "[Source pixiv](https://www.pixiv.net/en/artworks/#{file[..file.index("_p")-1]})"
      )
    end
  else
    File.open(check_image, 'rb') do |f|
      bot.api.send_photo(
        chat_id: channel_id,
        photo: Faraday::UploadIO.new(f, exten)
      )
    end
  end

  # 发送文档
  File.open(file, 'rb') do |f|
    bot.api.send_document(chat_id:channel_id, document: Faraday::UploadIO.new(f, exten))
  end

  # 安全移动文件
  FileUtils.mv(file, File.join("uploaded", file))
end

3. 额外优化:路径处理

手动拼接路径的方式在Windows下易出现转义问题,建议用File.join生成跨平台兼容路径:

# 替换压缩文件路径判断
compressed_file = File.join('compress', "#{file[0...file.index('.')]}.jpg")
if check_image.size > 5000000 && !File.exist?(compressed_file)
  p "compressing #{file}"
  system "mogrify -define jpeg:extent=5000kb -resize #{img_size}x#{img_size} -path compress -format jpg #{file}"
  check_image = compressed_file
end

# 移动文件时也用File.join
FileUtils.mv(file, File.join("uploaded", file))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 01:57:29