下载带有大量动态生成的PDF的ZIP文件的最佳方法是什么?

问题描述 投票:0回答:1

在我的Rails应用中,user每月最多可以创建3000 invoices。他/她还可以为每张发票生成发票PDF。这是即时发生的,即PDF永远不会保存在服务器上的任何位置。

我希望我的用户能够将all发票PDF作为单个ZIP文件下载。

我在当前解决方案中使用Prawn PDFZIP tricks gem

class InvoicesController < ApplicationController

  def index
    invoices = current_user.invoices
    respond_to do |format|
      format.zip do
        DownloadInvoiceArchive.call(invoices, response, view_context)
      end
    end
  end

end

class DownloadInvoiceArchive

  include ActionController::Live

  LIMIT = 100

  def self.call(invoices, response, view_context)
    zipname = "invoices.zip"
    disposition = "attachment; filename=\"#{zipname}\""

    response.headers["Content-Disposition"] = disposition
    response.headers["Content-Type"] = "application/zip"
    response.headers["Last-Modified"] = Time.now.httpdate.to_s
    response.headers["X-Accel-Buffering"] = "no"

    writer = ZipTricks::BlockWrite.new do |chunk|
      response.stream.write(chunk)
    end
    ZipTricks::Streamer.open(writer) do |zip|
      invoices.each_with_index do |invoice, index|
        break if index == LIMIT
        file_name = "#{invoice.number}.pdf"
        zip.write_deflated_file(file_name) do |file_writer|
          pdf = InvoicePdf.new(invoice, view_context)
          file_writer << pdf.render
        end
      end
    end
    response.stream.close
  end

end

但是,这种方法的性能非常差,因为它需要花费大量的时间来遍历数千张发票并为每张发票生成一个PDF。 (生成一个PDF会单独创建至少5个SQL查询。)

所以我的问题是如何在此处改善性能。

[一种选择是在后台作业中运行PDF生成,然后在准备就绪时通过电子邮件将下载链接发送给用户。但是应该将ZIP文件存储在哪里?在服务器的文件系统中还是在Amazon S3上?数据高度机密,下载后必须删除。

那么最好的方法是什么?感谢您的指导。

ruby-on-rails ruby pdf prawn
1个回答
0
投票

如果太长而无法在HTTP请求中处理,则必须将其移至后台作业。通过将生成的发票保存在服务器上,可以使其更快地运行,无论如何,BTW听起来还是个好主意,因为在许多国家/地区,发票必须以“不可更改的”数据格式存储。如果您的数据库与发票位于同一台服务器上,则可能不会引起任何重大的安全问题。

您是否没有保存它们的atm的特殊原因?

© www.soinside.com 2019 - 2024. All rights reserved.