Active Storage 默认不支持 XML 文件上传,因 Rails 7+ 的 content_type 白名单默认拦截 application/xml 和 text/xml;需在 config/initializers/active_storage.rb 中扩展 ActiveStorage.content_types_allowed_in_attachments 列表并保留原有类型。

Active Storage 默认不支持 XML 文件上传?
Active Storage 本身不限制文件类型,但 Rails 默认的 content_type 白名单会拦截 application/xml 和 text/xml。你上传 XML 文件时可能遇到 ActiveStorage::InvariableError 或静默失败(实际没存进 Blob),根本原因是 Rails 7+ 对非图片/文本/音视频等“常规类型”做了默认过滤。
- 检查日志里是否出现
Skipping Active Storage attachment: unsupported content type - 不是 Active Storage 不能存 XML,而是
ActiveStorage::Blob.create_after_upload!被中间件提前拒绝了 - 绕过方式不是改源码,而是显式声明允许类型
如何让 Active Storage 接收 XML 文件
在初始化配置中扩展允许的 MIME 类型列表。修改 config/initializers/active_storage.rb:
ActiveStorage.content_types_allowed_in_attachments = [ "text/plain", "text/csv", "application/xml", "text/xml", "application/xhtml+xml", *ActiveStorage.content_types_allowed_in_attachments ]
注意:*ActiveStorage.content_types_allowed_in_attachments 必须保留,否则会丢失原有支持类型(如 PNG、PDF)。如果用的是 Rails config.active_storage.content_types_allowed_in_attachments,写法略有不同。
- 重启应用后,
has_one_attached :config_file就能接收用户上传的.xml文件 - 前端无需改
,浏览器自动发送正确Content-Type - 验证时可用
record.config_file.blob.content_type.in?(%w[application/xml text/xml])
上传后怎么安全读取 XML 内容
Active Storage 的 download 方法返回原始字节,直接传给 Nokogiri::XML 可能触发 XXE(外部实体攻击),尤其当 XML 来自不可信用户时。
- 永远不要用
Nokogiri::XML(blob.download)—— 它默认启用外部实体解析 - 必须禁用外部实体:用
Nokogiri::XML(blob.download, nil, nil, Nokogiri::XML::ParseOptions::NOENT) - 更稳妥的做法是先下载到临时文件再解析,避免内存爆涨(大 XML 文件):
Ox.parse
- Active Storage 的优势在于统一接口(本地/ S3 / GCS 透明切换)、内置变体(虽 XML 不需要)、以及和 Action Text 的深度集成
- 真正要注意的是:XML 不是二进制资源,别误用
representable或试图生成预览图 - 如果业务需要校验 XML Schema(XSD),务必在
after_commit回调里做,而不是在控制器里阻塞上传流程
XML 文件体积小、结构固定、无渲染需求——Active Storage 是最省心的选择,前提是把 content_type 白名单和解析安全这两处补上。










