美文网首页哲学干货Ruby干货
使用open-uri遇到的问题,这个坑不小

使用open-uri遇到的问题,这个坑不小

作者: AQ王浩 | 来源:发表于2015-03-28 22:10 被阅读1176次

一、诡异的10kb 的问题

最近做项目的时候,修改了图片的上传方式。经过缜密的开发和测试,成功上线。
后台监控newrelic 提示

undefined method `path' for #<StringIO>

由于上传图片,是非常关键的步骤。大约有 1000rpm,但是为啥报错的仅仅只有那么几个例子呢?

经过详细的研究和实现。发现open-uri 有一个设置,对 <10kb的文件会将其设置为StringIO类,但是 >10kb 的文件会设置为 Tempfile类。

其实他的设置还是比较聪明的,我猜想作者的目的是不要让大量的小文件存在。所以设置了这个阀值。

上例子。

其中

http://yannini.qiniudn.com/lessthanten.png 是 <10kb 的文件  
http://yannini.qiniudn.com/1.png 是 >10kb 的文件

启动irb,

>> require "open-uri"
>> open("http://yannini.qiniudn.com/lessthanten.png")
=> #<StringIO:0x00000102b6e920 @base_uri=#<URI::HTTP:0x00000102b6eba0 URL:http://yannini.qiniudn.com/lessthanten.png>, @meta={"date"=>"Sat, 28 Mar 2015 13:43:04 GMT", "server"=>"nginx/1.4.4", "content-type"=>"image/jpeg", "content-length"=>"8157", "accept-ranges"=>"bytes", "access-control-allow-origin"=>"*", "access-control-max-age"=>"2592000", "cache-control"=>"public, max-age=31536000", "content-disposition"=>"inline; filename=\"lessthanten.png\"", "content-transfer-encoding"=>"binary", "etag"=>"\"Fg3HN9hK3Hy68nGT99MOSdtaafDx\"", "x-log"=>"mc.g;IO:1", "x-reqid"=>"BVsAAE70cUNUrc8T", "x-whom"=>"nb990", "x-qiniu-zone"=>"0", "age"=>"1", "x-via"=>"1.1 tzh55:8104 (Cdn Cache Server V2.0), 1.1 bjdxtck17:8 (Cdn Cache Server V2.0)", "connection"=>"keep-alive"}, @metas={"date"=>["Sat, 28 Mar 2015 13:43:04 GMT"], "server"=>["nginx/1.4.4"], "content-type"=>["image/jpeg"], "content-length"=>["8157"], "accept-ranges"=>["bytes"], "access-control-allow-origin"=>["*"], "access-control-max-age"=>["2592000"], "cache-control"=>["public, max-age=31536000"], "content-disposition"=>["inline; filename=\"lessthanten.png\""], "content-transfer-encoding"=>["binary"], "etag"=>["\"Fg3HN9hK3Hy68nGT99MOSdtaafDx\""], "x-log"=>["mc.g;IO:1"], "x-reqid"=>["BVsAAE70cUNUrc8T"], "x-whom"=>["nb990"], "x-qiniu-zone"=>["0"], "age"=>["1"], "x-via"=>["1.1 tzh55:8104 (Cdn Cache Server V2.0), 1.1 bjdxtck17:8 (Cdn Cache Server V2.0)"], "connection"=>["keep-alive"]}, @status=["200", "OK"]>
>> open("http://yannini.qiniudn.com/lessthanten.png").class
=> StringIO


>> open("http://yannini.qiniudn.com/1.png")
=> #<Tempfile:/var/folders/mj/q33ysmhn02v_xr430ftz6mnw0000gn/T/open-uri20150328-31267-1qyc4wr>
>> open("http://yannini.qiniudn.com/1.png").class        
=> Tempfile

很明显,两个文件最终生成的类不一致。
接着往下看,上传图片时,需要使用图片的真实路径。所以需要调用file.path 方法,但是 StringIO没有path方法,导致报错。

>> open("http://yannini.qiniudn.com/1.png").path
=> "/var/folders/mj/q33ysmhn02v_xr430ftz6mnw0000gn/T/open-uri20150328-31267-oyxvdv"
>> open("http://yannini.qiniudn.com/lessthanten.png").path
NoMethodError: undefined method `path' for #<StringIO:0x00000101b9d168>
    from (irb):16
    from /Users/wanghao/.rvm/rubies/ruby-2.1.1/bin/irb:11:in `<main>'
>>

二、解决方式

rails script目录下,新建一个 reset_open_uri.rb

if defined?(OpenURI) && OpenURI::Buffer.const_defined? (:StringMax)
  OpenURI::Buffer.send('remove_const', :StringMax)
  OpenURI::Buffer.send('const_set', :StringMax, 0)
end

然后在需要启动的开发或生产环境中,引入该配置即可

require(File.join(Rails.root, 'script/reset_open_uri.rb'))

这样,任何大小的文件都open时候最终都生成 Tempfile

三、清除大量的小图片

由于上述设置,大量的小图片生成。导致服务器的硬盘空间不足。
所以最后需要写一个定时任务,手动删除 cd /var/folders/mj/q33ysmhn02v_xr430ftz6mnw0000gn/T/ 下的关联文件。

参考

Undefined Method 'path' For StringIO in Ruby
Why does Ruby open-uri's open return a StringIO in my unit test, but a FileIO in my controller?

相关文章

  • 使用open-uri遇到的问题,这个坑不小

    一、诡异的10kb 的问题 最近做项目的时候,修改了图片的上传方式。经过缜密的开发和测试,成功上线。后台监控new...

  • 2019-05-23

    flutter 踩坑日记.... 我在使用TabBar配合TabBarView使用的时候遇到了这个问题setSta...

  • [Unity] Unable to load DLL 'Fire

    我在使用Unity接入Firebase,打包Android平台的时候,遇到了这个问题 其实这个问题是我自己坑了自己...

  • Swift 上传文件

    前言 最近在使用Vapor遇到很多的问题,坑也填了不少,下面就来说说由这个坑引发一系列的问题。 需求 在应用里,需...

  • Can't bind to 'rows' since it is

    angular 使用 ngx-datatable 遇到的坑 开始用这个组件的时候就遇到坑爹的事情,访问

  • swift server side framework -- v

    好久前尝试使用vapor遇到的坑,分享给遇到同样问题的同学 openssl失败 描述

  • mui 开发公众号网页 出现点击触发区域错位问题

    遇到此问题 及微信开发者工具问题 使用真机测试将不会出现此问题 被这个给坑了 做一下记录

  • React Navigation 问答录

    使用 React Navigation 遇到了不少坑,总结记录自己遇到过的问题 (连载) 当我重置 StackNa...

  • SuperPlayer iOS端填坑

    iOS 使用cocoapods 集成 SuperPlayer 遇到的坑: 这个坑也是苦了我几个小时,各种排查排除法...

  • NetworkExtension 的方法是用

    在做wifi分享的时候遇到了很多的问题,尤其是这个库的时候遇到很多坑爹的事情,写着文章只是为了不让自己忘记怎么使用...

网友评论

本文标题:使用open-uri遇到的问题,这个坑不小

本文链接:https://www.haomeiwen.com/subject/qjmnxttx.html