从 S3 托管文件将临时文件写入 Heroku
Writing temp files to Heroku from an S3 hosted file
我在 Heroku 上托管了一个 rails 应用程序。情况是这样的:用户应该能够使用 s3 将 PDF(Batch 的一个实例)上传到我们的应用程序;用户还应该能够获取已上传 PDF 的 s3 网址,并使用 HyPDF 通过指定文件路径和要拆分的所需页面(以创建 Essay 实例)将其拆分为更多 PDF。
所有这些都发生在对 /essays
的同一个 POST 请求中。
这是我今天一直在使用的代码:
def create
if params[:essay].class == String
batch_id = params[:batch_id].gsub(/[^\d]/, '').to_i
break_up_batch(params, batch_id)
redirect_to Batch.find(batch_id), notice: 'Essays were successfully created.'
else
@essay = Essay.new(essay_params)
respond_to do |format|
if @essay.save
format.html { redirect_to @essay, notice: 'Essay was successfully created.' }
format.json { render :show, status: :created, location: @essay }
else
format.html { render :new }
format.json { render json: @essay.errors, status: :unprocessable_entity }
end
end
end
end
# this is a private method
def break_up_batch(params, batch_id)
essay_data = []
# create a seperate essay for each grouped essay
local_batch = File.open(Rails.root.join('tmp').to_s + "temppdf.pdf" , 'wb') do |f|
f.binmode
f.write HTTParty.get(Batch.find(batch_id).document.url).parsed_response
f.path
end
params["essay"].split("~").each do |data|
data = data.split(" ")
hypdf_url = HyPDF.pdfextract(
local_batch,
first_page: data[1].to_i,
last_page: data[2].to_i,
bucket: 'essay101',
public: true
)
object = {student_name: data[0], batch_id: batch_id, url: hypdf_url[:url]}
essay_data << object
end
essay_data.each {|essay| Essay.create(essay)}
File.delete(local_batch)
end
我无法让文件显示在 Heroku 上,我正在检查 heroku run bash
和 ls tmp
。所以当method为运行时,一个空白文件上传到S3。我写了一些 jQuery 来填充隐藏字段,这就是为什么在代码中间有时髦的拆分。
由于 Heroku 的临时文件系统,我强烈建议您尽快将该文件从您的文件系统中删除。也许使用以下内容:
- 用户上传到S3(最好直接:https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails)
- 启动后台工作程序以获取文件并在内存中进行必要的处理
- 如果在正确处理文件时需要通知用户,请在您的数据库中设置一个 "status" 字段并允许前端应用程序轮询网络服务器以获取更新。向用户显示 "Processing",直到后台工作人员更改其状态。
此方法还允许您的 Web 进程快速响应,而不会占用资源,并可能触发 H12(请求超时)错误。
原来使用 File
class 并不是正确的方法。但是使用 Tempfile
有效!
def break_up_batch(params, batch_id, current_user)
essay_data = []
# create a seperate essay for each grouped essay
tempfile = Tempfile.new(['temppdf', '.pdf'], Rails.root.join('tmp'))
tempfile.binmode
tempfile.write HTTParty.get(Batch.find(batch_id).document.url).parsed_response
tempfile.close
save_path = tempfile.path
params["essay"].split("~").each do |data|
data = data.split(" ")
hypdf_url = HyPDF.pdfextract(
save_path,
first_page: data[1].to_i,
last_page: data[2].to_i,
bucket: 'essay101',
public: true
)
object = {student_name: data[0], batch_id: batch_id, url: hypdf_url[:url]}
essay_data << object
end
essay_data.each do |essay|
saved_essay = Essay.create(essay)
saved_essay.update_attributes(:company_id => current_user.company_id) if current_user.company_id
end
tempfile.unlink
end
我在 Heroku 上托管了一个 rails 应用程序。情况是这样的:用户应该能够使用 s3 将 PDF(Batch 的一个实例)上传到我们的应用程序;用户还应该能够获取已上传 PDF 的 s3 网址,并使用 HyPDF 通过指定文件路径和要拆分的所需页面(以创建 Essay 实例)将其拆分为更多 PDF。
所有这些都发生在对 /essays
的同一个 POST 请求中。
这是我今天一直在使用的代码:
def create
if params[:essay].class == String
batch_id = params[:batch_id].gsub(/[^\d]/, '').to_i
break_up_batch(params, batch_id)
redirect_to Batch.find(batch_id), notice: 'Essays were successfully created.'
else
@essay = Essay.new(essay_params)
respond_to do |format|
if @essay.save
format.html { redirect_to @essay, notice: 'Essay was successfully created.' }
format.json { render :show, status: :created, location: @essay }
else
format.html { render :new }
format.json { render json: @essay.errors, status: :unprocessable_entity }
end
end
end
end
# this is a private method
def break_up_batch(params, batch_id)
essay_data = []
# create a seperate essay for each grouped essay
local_batch = File.open(Rails.root.join('tmp').to_s + "temppdf.pdf" , 'wb') do |f|
f.binmode
f.write HTTParty.get(Batch.find(batch_id).document.url).parsed_response
f.path
end
params["essay"].split("~").each do |data|
data = data.split(" ")
hypdf_url = HyPDF.pdfextract(
local_batch,
first_page: data[1].to_i,
last_page: data[2].to_i,
bucket: 'essay101',
public: true
)
object = {student_name: data[0], batch_id: batch_id, url: hypdf_url[:url]}
essay_data << object
end
essay_data.each {|essay| Essay.create(essay)}
File.delete(local_batch)
end
我无法让文件显示在 Heroku 上,我正在检查 heroku run bash
和 ls tmp
。所以当method为运行时,一个空白文件上传到S3。我写了一些 jQuery 来填充隐藏字段,这就是为什么在代码中间有时髦的拆分。
由于 Heroku 的临时文件系统,我强烈建议您尽快将该文件从您的文件系统中删除。也许使用以下内容:
- 用户上传到S3(最好直接:https://devcenter.heroku.com/articles/direct-to-s3-image-uploads-in-rails)
- 启动后台工作程序以获取文件并在内存中进行必要的处理
- 如果在正确处理文件时需要通知用户,请在您的数据库中设置一个 "status" 字段并允许前端应用程序轮询网络服务器以获取更新。向用户显示 "Processing",直到后台工作人员更改其状态。
此方法还允许您的 Web 进程快速响应,而不会占用资源,并可能触发 H12(请求超时)错误。
原来使用 File
class 并不是正确的方法。但是使用 Tempfile
有效!
def break_up_batch(params, batch_id, current_user)
essay_data = []
# create a seperate essay for each grouped essay
tempfile = Tempfile.new(['temppdf', '.pdf'], Rails.root.join('tmp'))
tempfile.binmode
tempfile.write HTTParty.get(Batch.find(batch_id).document.url).parsed_response
tempfile.close
save_path = tempfile.path
params["essay"].split("~").each do |data|
data = data.split(" ")
hypdf_url = HyPDF.pdfextract(
save_path,
first_page: data[1].to_i,
last_page: data[2].to_i,
bucket: 'essay101',
public: true
)
object = {student_name: data[0], batch_id: batch_id, url: hypdf_url[:url]}
essay_data << object
end
essay_data.each do |essay|
saved_essay = Essay.create(essay)
saved_essay.update_attributes(:company_id => current_user.company_id) if current_user.company_id
end
tempfile.unlink
end