如何在 rails 上使用 ruby 将 excel 文件上传到 S3 存储桶
How to upload an excel file into S3 bucket using ruby on rails
在我们的 rails 6 项目中,我想将 excel 文件上传到 S3 存储桶并将文件 link 发送到电子邮件并提供从电子邮件下载 xls 功能。请帮助我。
我已经使用下面的代码生成了 excel 文件,并且还在我们的项目中设置了 S3 配置
xlsx = GenerateSpreadsheetService.new(all_data, file_name).call
现在我的问题是如何将上述 excel 文件上传到 S3 存储桶并将文件 link 发送到电子邮件并提供从电子邮件下载 xls 功能
class ImportCsvDataJob < ApplicationJob
queue_as :default
def perform(file_name, column)
begin
keywords = []
all_data = []
file_path = get_file_path(file_name)
spreadsheet = Roo::Excelx.new(file_path)
(2..spreadsheet.last_row).each do |i|
keywords << {"language_code": "en", "location_code": 2840, "keyword": "allintitle: #{spreadsheet.row(i)}"}
end
response = GetTaskService.new(keywords).call
response["tasks"].map{|task|
keyword = task["data"]["keyword"].gsub('allintitle: ','')
result = GetTaskService.new.get_values(task["id"])
all_data << {keyword: keyword.to_s, value: result["tasks"][0]["result"][0]["se_results_count"]}
}
## Create records
CsvImport.create(all_data)
## Generate excel file
xlsx = GenerateSpreadsheetService.new(all_data, file_name).call
## send email
SendEmailJob.perform_now(xlsx, file_name)
## remove temp storage file after processing
File.delete(Rails.root + "public/spreadsheets/#{file_name}")
rescue Exception => e
Rails.logger.info "--error-----#{e.message}--"
end
end
end
class GenerateSpreadsheetService
def initialize(data = [], file_name)
@data = data
@file_name = file_name
end
def call
ActionController::Base.new().render_to_string(template: "csv_imports/template.xlsx.axlsx", layout: false, formats: [:axlsx], locals: {:data => @data})
end
end
class SendEmailJob < ApplicationJob
queue_as :default
def perform(xlsx, file_name)
SendEmailService.new(xlsx, file_name).call
end
end
class SendEmailService
def initialize(xlsx, file_name)
@xlsx = xlsx
@email = "test@example.com"
@subject = "excel file"
@file_name = file_name
end
def call
KeywordMailer.send_csv(@email, @subject, @xlsx, @file_name).deliver_now!
end
end
https://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpRuby.html
亚马逊给你答案:
require 'aws-sdk-s3'
s3 = Aws::S3::Resource.new(region:'us-west-2')
obj = s3.bucket('bucket-name').object('key')
obj.upload_file('/path/to/source/file')
你只需要设置区域,bucket-name,然后最后一行的文件路径就是你存储这个xls文件的地方。看起来您正在使用一些随机文件名将其存储在 /public/spreadsheets。
我是怎么解决这个问题的?
生成excelsheet
time = Time.zone.now.strftime("%Y%m%d%H%M%S")
xlsx = GenerateSpreadsheetService.new(all_data, file_name).call
创建一个空目录
path = Tempfile.new("data_#{time}.xlsx").path
将excel文件写入此目录
file = File.open(path,"wb") {|f| f.write(xlsx) }
s3 = Aws::S3::Resource.new(region: APP_CONFIG["s3_region"], credentials: Aws::Credentials.new(APP_CONFIG["s3_access_key"], APP_CONFIG["s3_secret_key"]))
obj = s3.bucket(APP_CONFIG["s3_bucket"]).object("data_#{time}.xlsx")
obj.upload_file(path)
presigned_url = obj.presigned_url(:put, bucket: APP_CONFIG["s3_bucket"], key: "data_#{time}.xlsx", expires_in: 604800)
保存 public_url 和 presigned_url
FileUrl.create(key: "data_#{time}.xlsx", file_public_url: obj.public_url, file_presigned_url: presigned_url) if presigned_url.present?
在我们的 rails 6 项目中,我想将 excel 文件上传到 S3 存储桶并将文件 link 发送到电子邮件并提供从电子邮件下载 xls 功能。请帮助我。
我已经使用下面的代码生成了 excel 文件,并且还在我们的项目中设置了 S3 配置
xlsx = GenerateSpreadsheetService.new(all_data, file_name).call
现在我的问题是如何将上述 excel 文件上传到 S3 存储桶并将文件 link 发送到电子邮件并提供从电子邮件下载 xls 功能
class ImportCsvDataJob < ApplicationJob
queue_as :default
def perform(file_name, column)
begin
keywords = []
all_data = []
file_path = get_file_path(file_name)
spreadsheet = Roo::Excelx.new(file_path)
(2..spreadsheet.last_row).each do |i|
keywords << {"language_code": "en", "location_code": 2840, "keyword": "allintitle: #{spreadsheet.row(i)}"}
end
response = GetTaskService.new(keywords).call
response["tasks"].map{|task|
keyword = task["data"]["keyword"].gsub('allintitle: ','')
result = GetTaskService.new.get_values(task["id"])
all_data << {keyword: keyword.to_s, value: result["tasks"][0]["result"][0]["se_results_count"]}
}
## Create records
CsvImport.create(all_data)
## Generate excel file
xlsx = GenerateSpreadsheetService.new(all_data, file_name).call
## send email
SendEmailJob.perform_now(xlsx, file_name)
## remove temp storage file after processing
File.delete(Rails.root + "public/spreadsheets/#{file_name}")
rescue Exception => e
Rails.logger.info "--error-----#{e.message}--"
end
end
end
class GenerateSpreadsheetService
def initialize(data = [], file_name)
@data = data
@file_name = file_name
end
def call
ActionController::Base.new().render_to_string(template: "csv_imports/template.xlsx.axlsx", layout: false, formats: [:axlsx], locals: {:data => @data})
end
end
class SendEmailJob < ApplicationJob
queue_as :default
def perform(xlsx, file_name)
SendEmailService.new(xlsx, file_name).call
end
end
class SendEmailService
def initialize(xlsx, file_name)
@xlsx = xlsx
@email = "test@example.com"
@subject = "excel file"
@file_name = file_name
end
def call
KeywordMailer.send_csv(@email, @subject, @xlsx, @file_name).deliver_now!
end
end
https://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpRuby.html
亚马逊给你答案:
require 'aws-sdk-s3'
s3 = Aws::S3::Resource.new(region:'us-west-2')
obj = s3.bucket('bucket-name').object('key')
obj.upload_file('/path/to/source/file')
你只需要设置区域,bucket-name,然后最后一行的文件路径就是你存储这个xls文件的地方。看起来您正在使用一些随机文件名将其存储在 /public/spreadsheets。
我是怎么解决这个问题的?
生成excelsheet
time = Time.zone.now.strftime("%Y%m%d%H%M%S")
xlsx = GenerateSpreadsheetService.new(all_data, file_name).call
创建一个空目录
path = Tempfile.new("data_#{time}.xlsx").path
将excel文件写入此目录
file = File.open(path,"wb") {|f| f.write(xlsx) }
s3 = Aws::S3::Resource.new(region: APP_CONFIG["s3_region"], credentials: Aws::Credentials.new(APP_CONFIG["s3_access_key"], APP_CONFIG["s3_secret_key"]))
obj = s3.bucket(APP_CONFIG["s3_bucket"]).object("data_#{time}.xlsx")
obj.upload_file(path)
presigned_url = obj.presigned_url(:put, bucket: APP_CONFIG["s3_bucket"], key: "data_#{time}.xlsx", expires_in: 604800)
保存 public_url 和 presigned_url
FileUrl.create(key: "data_#{time}.xlsx", file_public_url: obj.public_url, file_presigned_url: presigned_url) if presigned_url.present?