新手问题 ckeditor + carrierwave-aliyun 开发环境正常,生产环境上传图片提示 InvalidArgument 。

gxlonline · 2017年11月05日 · 最后由 gxlonline 回复于 2017年11月06日 · 2711 次阅读

版本情况

Ubuntu14.04, Ruby2.4.1, Rails 5.1.4 , passenger-5.1.11

情况描述

使用 @huacnlee 的 carrierwave-aliyun,在本地用 ckeditor 编辑器上传图片一切正常,并且能够将文件上传至 aliyun oss,但在生产环境下一直提示

InvalidArgument The bucket POST must contain the specified 'key'.
If it is specified, please check the order of the fields 59FF1BBE6B85238B77470D50 static.abc.com key

查 aliyun oss 文档 InvalidArgument:”表单域没有指定 key,或者放在了表单域 file 后“。

另外,在不使用 ckeditor 的情况,直接用普通表单提交,在生产环境下,是能够正常上传文件至 oss。

config/initializers/carrierwave.rb

CarrierWave.configure do |config|
  config.storage           = :aliyun
  config.aliyun_access_id  = "XXX"
  config.aliyun_access_key = 'XXX'
  # 你需要在 Aliyum OSS 上面提前创建一个 Bucket
  config.aliyun_bucket     = "XXX"
  # 是否使用内部连接,true - 使用 Aliyun 主机内部局域网的方式访问  false - 外部网络访问
  config.aliyun_internal   = false
  # 配置存储的地区数据中心,默认: cn-hangzhou
  config.aliyun_area     = "cn-shenzhen"
  # 使用自定义域名,设定此项,carrierwave 返回的 URL 将会用自定义域名
  # 自定义域名请 CNAME 到 you_bucket_name.oss-cn-hangzhou.aliyuncs.com (you_bucket_name 是你的 bucket 的名称)
  config.aliyun_host       = "http://static.XXX.com"
  # Bucket 为私有读取请设置 true,默认 false,以便得到的 URL 是能带有 private 空间访问权限的逻辑
  config.aliyun_private_read = true
end

config/initializers/ckeditor.rb

Ckeditor.setup do |config|
  require 'ckeditor/orm/active_record'
  config.asset_path = 'http://static.xxx.com'
  config.assets_languages = ['zh-cn']
  config.assets_plugins = ['image']
end

uploaders/ckeditor_picture_uploader.rb

require 'carrierwave'
class CkeditorPictureUploader < CarrierWave::Uploader::Base
  include Ckeditor::Backend::CarrierWave
  include CarrierWave::MiniMagick
  storage :aliyun
  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{Time.now.strftime("%Y%m%d")}"
  end
  process :extract_dimensions
  version :content do
    process resize_to_limit: [800, 800]
  end
  def extension_white_list
    Ckeditor.image_file_types
  end
  def filename
    "#{secure_token}.#{file.extension}" if original_filename.present?
  end

  protected
      def secure_token
        var = :"@#{mounted_as}_secure_token"
        model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
      end
end

app/assets/javascripts/ckeditor/config.js

CKEDITOR.editorConfig = function( config )
{
  config.language = 'zh-CN';
  config.filebrowserImageUploadUrl = "/ckeditor/pictures";
  config.allowedContent = true;
};

解决办法

将配置文件中自定义 asset_path 注释掉,不知道为什么。

config/initializers/ckeditor.rb

Ckeditor.setup do |config|
  # config.asset_path = 'http://static.xxx.com'
end

carrierwave.rb 如果设置 aliyun_private_read = true,自定义 aliyun_host 会不起作用,仍然返回 aliyun 本身的地址。(不影响使用)

config/initializers/carrierwave.rb

config.aliyun_access_id  = "XXX"
config.aliyun_access_key = 'XXX'
config.aliyun_bucket     = "XXXicom"
config.aliyun_internal   = false
config.aliyun_area     = "cn-shenzhen"
config.aliyun_host       = "http://static.XXX.com"
config.aliyun_private_read = true

另外的问题

如果设置 OSS 为私有,CKeditor 上传图片成功后,返回的地址带有 Expires,这样直接将图片地址插入内容中是行不通的,失效时间一到,图片就不能访问了。除非使用以下方式访问,才会生成新的访问地址:

ckeditor_asset.file.url

但 CKeditor 是把 url 硬编进内容的,目前想到办法:

  1. 把 OSS 设成公共读
  2. show content 时,遍历内容中的图片地址,然后替换。

方法 2 太麻烦了,目前还没想到更好的解决办法。

huacnlee 关闭了讨论。 11月07日 16:08
需要 登录 后方可回复, 如果你还没有账号请 注册新账号