Coder Social home page Coder Social logo

activestorage-aliyun's Introduction

ActiveStorage Aliyun Service

Wraps the Aliyun OSS as an Active Storage service, use Aliyun official Ruby SDK for upload.

Gem Version build

Installation

Add this line to your application's Gemfile:

gem "activestorage-aliyun"

And then execute:

$ bundle

Usage

NOTE! Current document work for Rails 6.1, if you are using Rails 6.0, please visit: https://github.com/huacnlee/activestorage-aliyun/tree/v0.6.4 You can also to use activestorage-aliyun 1.0.0 in Rails 6.0

config/storage.yml

aliyun:
  service: Aliyun
  access_key_id: 'your-oss-access-key-id'
  access_key_secret: 'your-oss-access-key-secret'
  bucket: 'bucket-name'
  endpoint: 'https://oss-cn-beijing.aliyuncs.com'
  # path prefix, default: /
  path: 'my-app-files'
  # Bucket public: true/false, default: true, for generate public/private URL.
  public: true

Custom Domain

aliyun:
  service: Aliyun
  access_key_id: 'your-oss-access-key-id'
  access_key_secret: 'your-oss-access-key-secret'
  bucket: 'bucket-name'
  endpoint: 'https://oss-cn-beijing.aliyuncs.com'
  public: false
  # Custom host for get file url, if this present, upload still use `endpoint`, but download url will use this.
  host: 'https://file.myhost.com'

Use for image url

Original File URL:

<%= image_tag @photo.image.url %>

Thumb with OSS image service:

class Photo < ApplicationRecord
  def image_thumb_url(process)
    self.image.url(params: { "x-oss-process" => process })
  end
end

And then:

<%= image_tag @photo.image_thumb_url("image/resize,h_100,w_100") %>

Use for file download

If you want to get original filename (Include Chinese and other UTF-8 chars), for example: 演示文件 download.zip, you need present disposition: :attachment option.

#
<%= image_tag @photo.image.url(disposition: :attachment) %>

Contributing

Run test

$ bin/test test/activestorage_aliyun_test.rb
# run a line
$ bin/test test/activestorage_aliyun_test.rb:129

License

The gem is available as open source under the terms of the MIT License.

activestorage-aliyun's People

Contributors

adamshen avatar ayamomiji avatar chloerei avatar clwy-cn avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar huacnlee avatar waruboy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

activestorage-aliyun's Issues

是否可以增加一个上传的endpoint?

背景是这样的,我在使用阿里云的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
...

如何获取临时授权 STS

需要客户端通过 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

使用 Direct Upload 上传成功后,提交表单报签名错误

配置结构与 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):

而实际数据也已经保存成功。

Aliyun::OSS::ServerError: You must provide the Content-Length HTTP header.

正常表单上传,有时候会报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

download_chunk 方法没有实现

直传的时候会有NotImplementedError

继承ActiveStorage::Service时 download_chunk 没有实现 T T,不知道有没有空加上呢。

windows环境下报错

看源码中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

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'

Can not override response header for an anonymous user

我调用 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 会得到如下错误

image

去掉查询参数反而不会有报错:

https://jrgcdn1.oss-cn-beijing.aliyuncs.com/development/imvla2sv9m9bzch5n5uqj1o3d4mk

得到图片内容。

难道我调用了 service_url 后要自行删掉查询参数?

不太理解,请指教。

direct_upload在rails 6.1下有问题

操作一

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的记录。

结论:

初步判断,

  • 在model中配置的service: :aliyun,在direct_upload方式下,完全没有生效。
  • 非direct_upload方式下,可以正确的上传到阿里云oss

我不确定是Rails的问题,还是activestorage-aliyun的问题?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.