预期结果
即使文件可以像图像一样在浏览器中显示,也强制下载文件。
问题
我在使用
rails_blob_url(file, disposition: 'attachment')
或 file.url(disposition: 'attachment')
时遇到问题,这可能是相同的?文件的响应头始终是 content-disposition: inline; filename="image.png"; filename*=UTF-8''image.png
在我的本地开发机器(使用本地文件存储)上,它对于图像也运行得很好 - 所有内容都会被强制下载。在我使用谷歌云存储的暂存环境中,似乎配置附件被忽略了。 GCS 文件上没有设置元数据配置,因此文档指出它应该使用提供的查询字符串(响应内容配置和响应内容类型)。所有文件都是私有的,因此我们使用signed_url。
我创建了一种调试方法 - 基本上使用与主动存储内部相同的方法..
def download_url
disposition = "attachment"
service = @file.service
expires_in = 300
if service.name == :google
gcs_config = Rails.application.config.active_storage.service_configurations['google']
storage = Google::Cloud::Storage.new(
project_id: gcs_config['project'],
credentials: gcs_config['credentials']
)
bucket = storage.bucket(gcs_config['bucket'])
blob = bucket.file(@file.key, skip_lookup: true)
content_disposition_formatted = ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: @file.filename.sanitized)
args = {
expires: expires_in,
query: {
"response-content-disposition" => content_disposition_formatted,
"response-content-type" => @file.content_type
}
}
logger.info "X"*80
logger.info @file.filename
logger.info "X"*80
logger.info args.inspect
logger.info "X"*80
blob.signed_url(**args)
else
rails_blob_url(@file, disposition: disposition, expires_in: expires_in)
end
end
有什么想法如何强制执行此操作吗?应该是有可能的——对吧?!
使用直接上传时,gcs 存在 activestorage bug
activestorage/lib/active_storage/service/s3_service.rb#headers_for_direct_upload
。它将内容处置元数据设置为内联,目前获取内容处置工作的查询参数的唯一方法是清除内容处置元数据。
这是清除它的丛林方法:
def clear_content_disposition
return unless file.service.name == :google
gcs_config = Rails.application.config.active_storage.service_configurations['google']
storage = Google::Cloud::Storage.new(
project_id: gcs_config['project'],
credentials: gcs_config['credentials']
)
bucket = storage.bucket(gcs_config['bucket'])
blob = bucket.file(file.key, skip_lookup: true)
blob.content_disposition = nil
end