Ruby升级到3.0.2后Rails文件上传报TypeError: can't dump File如何解决?
问题原因确认
你遇到的TypeError: can't dump File错误确实是Marshal.dump尝试序列化文件上传对象导致的:Ruby的File、Tempfile以及Rails的ActionDispatch::Http::UploadedFile类型都包含IO流资源,本身就不支持Marshal序列化操作。
升级后才触发报错的原因是:旧版本dalli客户端或低版本Rails的缓存逻辑会自动过滤不可序列化的对象,而切换到官方mem_cache_store+高版本Rails后,缓存写入前会强制对所有内容执行序列化和压缩,就触发了该错误。另外注意你给出的缓存配置存在笔误:mem_cached_store多了末尾的d,正确配置名是mem_cache_store,错误的配置也会导致缓存逻辑行为异常。
解决方案
- 首先修正缓存配置的笔误,正确配置参考:
config.cache_store = :mem_cache_store # 临时规避可关闭压缩,不推荐作为最终方案 # config.cache_store = :mem_cache_store, compress: false
- 从根源避免将文件对象存入session/flash:你之前仅清理params的内容无效,因为Rails如果在请求处理过程中(比如校验失败回显、自动存储历史请求参数等逻辑)自动把参数写入了flash或session,需要同步清理这两个位置的文件对象,在上传处理的控制器动作末尾添加如下逻辑:
# 清理所有参数中的上传文件对象 params.transform_values! do |val| next val unless [IO, Tempfile, ActionDispatch::Http::UploadedFile].any? { |type| val.is_a?(type) } nil end # 清理flash中可能存储的文件对象 flash.transform_values! do |val| next val unless val.is_a?(Hash) val.transform_values! do |v| [IO, Tempfile, ActionDispatch::Http::UploadedFile].any? { |type| v.is_a?(type) } ? nil : v end end # 清理session中可能存储的历史请求参数里的文件对象,键名根据你的业务逻辑调整 session[:last_request_params]&.delete(:image)
- 如果你没有特殊需求需要将session存入缓存,可以将session存储改为默认的cookie_store,避免session序列化触发缓存写入逻辑,配置修改为:
# config/initializers/session_store.rb Rails.application.config.session_store :cookie_store, key: '_你的应用标识_session'
内容的提问来源于stack exchange,提问作者mohit chavda
相关产品推荐
相关产品推荐

