React Native多图上传时出现ActiveSupport::MessageVerifier::InvalidSignature错误
ActiveSupport::MessageVerifier::InvalidSignature错误 使用React Native Expo开发客户端,上传两张图片至部署在render.com的Rails 7.0.6 API时触发ActiveSupport::MessageVerifier::InvalidSignature错误,其他功能正常。以下是相关代码及错误信息:
客户端上传代码
const onSubmit = async (values) => { const formData = new FormData(); formData.append("claim[category_id]", category); formData.append("claim[client_id]", client); formData.append("claim[location]", JSON.stringify(location)); formData.append("claim[comment]", values.comment); formData.append("claim[forwarded]", "false"); formData.append("claim[user_id]", user.id); for (let i = 0; i < images.length; i++) { formData.append("claim[images][]", images[i]); } if ( values.category && values.client && values.location && images.length === 2 ) { const response = await axios.post(`${GENERAL_URL}/claims`, formData, { headers: { "Content-Type": "multipart/form-data", }, }); const { success, claims } = response.data; if (success) { dispatch(addClaim(claims)); Alert.alert("CONFIRMATION", "The Claim has been submitted", [ null, { text: "OK", onPress: () => navigation.navigate("Explore") }, ]); } else { alert("Oops! something went wrong, please try again"); } } else { alert("Please fill in all fields"); } };
服务器错误日志
Started POST "/api/v1/claims" for 172.71.146.145 at 2023-07-06 11:21:52 +0000 Processing by Api::V1::ClaimsController#create as JSON Parameters: {"claim"=>{"images"=>["file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fclaimsapp-e6f181ad-9716-464f-b689-fa016d86a564/Camera/8368dd02-db36-4fac-a411-b221e2e59cbb.jpg", "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fclaimsapp-e6f181ad-9716-464f-b689-fa016d86a564/Camera/e23136d2-b43a-4797-a626-50d0f917b896.jpg"], "category_id"=>"1", "client_id"=>"2", "location"=>"{\"altitude\":-13.300000190734863,\"heading\":0,\"latitude\":40.3746823,\"longitude\":49.8341172,\"altitudeAccuracy\":5.68895149230957,\"speed\":0,\"accuracy\":22.576000213623047}", "comment"=>"Test", "forwarded"=>"false", "user_id"=>"1"}} Completed 500 Internal Server Error in 290ms (ActiveRecord: 14.3ms | Allocations: 10572) FATAL -- : [d8db3e20-d76c-4258-a7db-fb13428d4a2f] ActiveSupport::MessageVerifier::InvalidSignature (ActiveSupport::MessageVerifier::InvalidSignature): app/controllers/api/v1/claims_controller.rb:40:in `create'
Rails API创建方法
def create @api_v1_claim = Claim.new(api_v1_claim_params) if @api_v1_claim.save updated_claims = Claim.where(user_id: @api_v1_claim.user_id) render json: { success: true, claims: updated_claims, code: 2201 } else render json: @api_v1_claim.errors, status: :unprocessable_entity end end private def api_v1_claim_params params.require(:claim).permit(:comment, :location, :forwarded, :user_id, :client_id, :category_id, images: []) end
Claim模型
class Claim < ApplicationRecord belongs_to :user belongs_to :client belongs_to :category has_many_attached :images def image_urls if images.attached? images.map do |image| Rails.application.routes.url_helpers.url_for(image, only_path: true) end end end end
ClaimSerializer
class ClaimSerializer < ActiveModel::Serializer include JSONAPI::Serializer attributes :id, :location, :comment, :forwarded, :category_id, :user_id, :client_id, :images, :image_urls end
使用环境:Ruby 3.1.3p185、Rails 7.0.6、React Native Expo
问题原因分析
从错误日志可见,客户端上传的images参数是本地文件路径字符串(file:///...),而非实际文件二进制数据。Rails处理Active Storage附件时,会尝试验证路径签名,但这些本地路径未经过Rails签名处理,因此触发InvalidSignature错误。
同时,客户端手动设置Content-Type: multipart/form-data虽然格式正确,但FormData中未包含文件对象,导致Rails无法正确解析文件。
解决步骤
1. 修复客户端上传逻辑,传递正确的文件对象
在React Native Expo中,相机/相册获取的图片需转换为FormData可识别的文件对象,而非直接传递本地路径。假设images数组是Expo ImagePicker返回的对象,修改如下:
for (let i = 0; i < images.length; i++) { const image = images[i]; const file = { uri: image.uri, type: image.type || 'image/jpeg', name: image.fileName || `image-${i}.jpg` }; formData.append("claim[images][]", file); }
2. 移除手动设置的Content-Type(推荐)
Axios发送FormData时会自动生成包含boundary的正确Content-Type,手动设置可能导致边界符丢失,引发解析错误。可删除以下代码:
// headers: { // "Content-Type": "multipart/form-data", // },
3. 验证Rails配置正确性
- 确认
config/storage.yml配置了正确的存储服务(生产环境推荐使用云存储,如S3); - 检查
config/application.rb中已启用Active Storage:require "active_storage/engine" - 确保已执行
rails active_storage:install及数据库迁移。
4. 修复Serializer错误
当前ClaimSerializer直接序列化images(Active Storage附件对象)会导致错误,只需保留image_urls字段:
class ClaimSerializer < ActiveModel::Serializer include JSONAPI::Serializer attributes :id, :location, :comment, :forwarded, :category_id, :user_id, :client_id, :image_urls end
内容的提问来源于stack exchange,提问作者Emmanuel Mhango

