huacnlee / activestorage-aliyun Goto Github PK
View Code? Open in Web Editor NEWWraps the Aliyun OSS as an Active Storage service.
License: MIT License
Wraps the Aliyun OSS as an Active Storage service.
License: MIT License
direct upload 方式
我调用 service_url 的到
https://jrgcdn1.oss-cn-beijing.aliyuncs.com/development/imvla2sv9m9bzch5n5uqj1o3d4mk?response-content-disposition=inline%3B+filename%3D%22hi%22%3B+filename%2A%3DUTF-8%27%27hi&response-content-type=image%2Fpng
然而用浏览器访问这个 url 会得到如下错误
去掉查询参数反而不会有报错:
https://jrgcdn1.oss-cn-beijing.aliyuncs.com/development/imvla2sv9m9bzch5n5uqj1o3d4mk
得到图片内容。
难道我调用了 service_url 后要自行删掉查询参数?
不太理解,请指教。
README 中没有说明
Rails 6.1中,对active storage,在模型中增加了service新的配置方法,例如:
# models/user.rb
has_one_attached :avatar, service: :aliyun
development.rb中,未做修改,保持了默认
# config/environments/development.rb
config.active_storage.service = :local
非direct_upload文件时,可以正常上传到阿里云oss
<%= form.file_field :avatar %>
使用direct_upload传文件时,依然上传到本地,而不是阿里云oss上。也就说模型中配置的service,根本没有生效。
<%= form.file_field :avatar, direct_upload: true %>
chrome的netwok中,看不到请求阿里云oss的记录。
模型中,不配置service
# models/user.rb
has_one_attached :avatar
development.rb中,修改为:aliyun
# config/environments/development.rb
config.active_storage.service = :aliyun
再次测试direct_upload文件,可以正确上传到阿里云oss了。
chrome的netwok中,也可以看到请求阿里云oss的记录。
初步判断,
我不确定是Rails的问题,还是activestorage-aliyun的问题?
看源码中AliyunService的initialize代码中使用了/dev/null路径做为阿里日志路径:
module ActiveStorage
class Service::AliyunService < Service
def initialize(**config)
Aliyun::Common::Logging.set_log_file("/dev/null")
@config = config
......
导致windows环境下使用本gem时报错
正常表单上传,有时候会报Aliyun::OSS::ServerError
,一段时间基本上是必现,提示缺少Content-Length参数,不过发现通过direct upload方式上传是不会报错的。
=> #<ActionController::Parameters {"_method"=>"put", "authenticity_token"=>"xxxxxxx", "user"=>#<ActionController::Parameters {"avatar"=>#<ActionDispatch::Http::UploadedFile:0x00007fc34934b728 @tempfile=#<Tempfile:/var/folders/s9/g41qq3bs7dv10n9lt7z4st5r0000gn/T/RackMultipart20210917-28937-o36uet.jpeg>, @original_filename="71670020_415058982543577_8058120922903287954_n.jpeg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"71670020_415058982543577_8058120922903287954_n.jpeg\"\r\nContent-Type: image/jpeg\r\n">, "type"=>"local"} permitted: false>, "controller"=>"users", "action"=>"profile", "format"=>"2"} permitted: false>
Aliyun::OSS::ServerError: You must provide the Content-Length HTTP header. RequestId: xxxxxxxxxx
背景是这样的,我在使用阿里云的OSS,机器的带宽有限,每次上传都是走公网的endpoint,如果上传大图就跪了。所以我希望上传的时候可以用内网的endpoint,然后获取service_url的时候是拿公网的host。
我目前使用的Rails版本是6.0
目前我的解决方案是这样的,个人感觉不是特别好。
# lib/active_storage_blob_extension.rb
module ActiveStorageBlobExtension
extend ActiveSupport::Concern
included do
def cdn_service_url
if ENV['CDN_HOST'].present?
"#{ENV['CDN_HOST']}/#{self.key}"
else
self.service_url
end
end
end
end
# config/application.rb
...
config.to_prepare do
ActiveStorage::Blob.send :include, ::ActiveStorageBlobExtension
end
...
配置结构与 README 中相同,在 Direct Upload 上传成功后,使用 signed_id
提交表单,抛出 500 错误如下:
Aliyun::OSS::ServerError (The request signature we calculated does not match the signature you provided. Check your key and signing method. RequestId: XXXXXX):
而实际数据也已经保存成功。
需要客户端通过 js 直传 OSS,内嵌 iframe 无法直接通过 /rails/active_storage/direct_uploads
上传,需要获取 STS 后再上传 OSS。
# routes.rb
namespace :api do
get :sts, to: 'oss#sts'
end
# controller.rb
def sts
# new file parameters
# params[:filename] => 'test.txt' && params[:byte_size] => 710221
# old file information
# ActiveStorage::Blob.find_by_filename(params[:filename]) => #<ActiveStorage::Blob id: 33, key: "phecdsvaqca2q0h4tacscis7r7wl", filename: "test.txt", ... byte_size: 689744 ...>
# Get direct upload signed url by `url_for_direct_upload` ?
end
本地上传没有问题
上传到阿里云报错了
RestClient::SSLCertificateNotVerified (SSL_connect returned=1 errno=0 state=error: certificate verify failed):
直传的时候会有NotImplementedError
继承ActiveStorage::Service时 download_chunk 没有实现 T T,不知道有没有空加上呢。
storate.yml
local:
service: Aliyun
access_key_id: "*******"
access_key_secret: "******"
bucket: "product"
endpoint: "http://oss-cn-beijing.aliyuncs.com"
# path prefix, default: /
path: "/product"
# Bucket mode: [public, private], default: public
mode: "private"
model
class Product < ApplicationRecord
belongs_to :category
has_many :order_items
has_one_attached :product_image #产品首图
enum status:{
'未发布': false,
'已发布': true
}
end
views
<%=f.file_field :product_image %>
controller.rb
create方法代码
@product = Product.new(product_params)
@product.save
private
def product_params
params.require(:product).permit!
end
出现一下oss服务问题:
Aliyun::OSS::ServerError (The specified object is not valid. RequestId: 5AF11498A645AE2A87914BD3):
app/controllers/admin/products_controller.rb:12:in `create'
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.