我尝试通过DirectUpload / ActiveStorage / Rails 6用ajax添加一些图像。我使用ActiveStorage支持的先决条件,以便将DirectUpload与Jquery结合使用:https://edgeguides.rubyonrails.org/active_storage_overview.html#integrating-with-libraries-or-frameworks
const upload = new DirectUpload(file, url)
upload.create((error, blob) => {
if (error) {
// Handle the error
} else {
// Add an appropriately-named hidden input to the form with a
[..]
console.log(blob.key);
}
})
在我的主机上,它适用于所有文件。但是,当我尝试将应用程序发布到主机中时,在DirectUpload请求之后,某些文件出现错误,总是相同的:
Completed 422 Unprocessable Entity in 2ms (ActiveRecord: 0.0ms | Allocations: 689)
我在Webtools浏览器中查看了XHR请求,但是有效负载似乎在可以工作的文件中相同,而在另一个文件中则失败:
{id: 219, key: "v2v1aqlk8gyygcc4smjeh0bbuc59", filename: "groupama logo.jpeg",…}
id: 219
key: "v2v1aqlk8gyygcc4smjeh0bbuc59"
filename: "logo.jpeg"
content_type: "image/jpeg"
metadata: {}
byte_size: 17805
checksum: "3GIVi2kNKClfH+d9HGYOfkA=="
created_at: "2020-04-09T08:25:40.000+02:00"
signed_id: "eyJfcmFpbHMiOnsibWVzc2zaFnZSI6IkJBaHBBZHM9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--7c0750cb8c86a955a04fa9a11dc5389cdeb5e7b0"
attachable_sgid: "BAh7CEkiCGdpZAY6BkVUSSIxsaZ2lkOi8vYXBwL0FjdGl2ZVN0b3JhZ2U6OkJsb2IvMjE5P2V4cGlyZXNfaW4GOwBUSSIMcHVycG9zZQY7AFRJIg9hdHRhY2hhYmxlBjsAVEkiD2V4cGlyZXNfYXQGOwBUMA==--64a945c38dc5d85c05156da50b9c38819b106e10"
direct_upload: {,…}
url: "http://localhost:8491/rails/active_storage/disk/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaDdDVG9JYTJWNVNTSWhkakoyTVdGeGJHczRaM2w1WjJOak5ITnRhbVZvTUdKaWRXTTFPUVk2QmtWVU9oRmpiMjaUwWlc1MFgzUjVjR1ZKSWc5cGJXRm5aUzlxY0dWbkJqc0dWRG9UWTI5dWRHVnVkRjlzWlc1bmRHaHBBbzFGT2cxamFHVmphM04xYlVraUhUTkhTVlpwTW10T1MwTnNaa2dyT1VoSFdVOW1hMEU5UFFZN0JsUT0iLCJleHAiOiIyMDIwLTA0LTA5VDA2OjMwOjQwLjg5NFoiLCJwdXIiOiJibG9iX3Rva2VuIn19--a2acedc0924f735c5cc08db8c4b76f76accc3c8d"
headers: {Content-Type: "image/jpeg"}
我尝试了此解决方案,但猴子补丁对我不起作用,另一种解决方案似乎不起作用:Rails API ActiveStorage DirectUpload produce 422 Error InvalidAuthenticityToken
[我注意到,当我尝试在不使用DirectUpdate的情况下将徽标图像文件上传到输入文件时,该文件已正确发送到我的服务器。
= f.file_field :logos, direct_upload: true
您有什么想法要测试吗?
我的问题来自用于复制文件的IO。在ActiveStorage::DiskController#update
中,Rails使用request.body
和IO.CopyStream
创建文件,并完成了一个校验和文件以验证创建的文件。并且检查失败并抛出422 http错误。
[我注意到,IO流在开发人员模式下是String_IO
,而在我的主机上,IO是Uswgi_IO
。因为我的托管人通过Uswgi交付了ruby on rails应用程序。uwsgi_io不包含length或size方法,当ActiveStorage使用此IO创建文件时,文件的大小很奇怪。奇怪的是太大。
我注意到是否分配了RAW_POST_DATA
,然后request.body
返回了String_IO
。并通过request.raw_post
直接读取主体,方法为request.content_length
:
raw_post_body.read(content_length)
https://api.rubyonrails.org/classes/ActionDispatch/Request.html#method-i-body
我创建了一个继承自ActiveStorage::DiskController
的新控制器,以便在RAW_POST_DATA
动作之前分配Disk#update
。
class UploadController < ActiveStorage::DiskController
def update
request.env['RAW_POST_DATA'] = request.body.read(request.content_length)
super
end
end
然后,我覆盖了我的ActiveStorage disk#update路由:
put '/rails/active_storage/disk/:encoded_token', to: 'upload#update
而且有效!
ActionText与ActiveStorage一起用于存储图像,但是图像过大也存在相同的问题。我的补丁程序也允许在主机上制作ActionText。