使用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
相关产品推荐
相关产品推荐

