我正在构建一个非常简单的Web工具,用户可以在其中上传CSV文件,然后对该文件进行处理,然后可以立即下载结果CSV。
上传表单:
<%= form_tag '/upload', multipart: true do %>
<%= file_field_tag :csv %>
<%= submit_tag 'Import CSV' %>
<% end %>
上传和下载操作:
def upload
original_csv = params[:csv]
p original_csv.path # /var/folders/71/chp2vrc92_19b3jt2fcwhvp80000gn/T/RackMultipart20181025-11469-25guh5.csv
redirect_to result_path(file_path: original_csv.path)
end
def result
p params[:file_path] # /var/folders/71/chp2vrc92_19b3jt2fcwhvp80000gn/T/RackMultipart20181025-11469-25guh5.csv
output_csv = CSV.generate do |csv|
CSV.foreach(params[:file_path], headers: true) do |row|
#############################################
# "No such file or directory @ rb_sysopen" #
# exception is thrown #
#############################################
# each row data is being processed here
csv << row
end
end
# Download the file into user's computer
send_data output_csv
end
从注释中可以看到,此方法不起作用,因为临时文件路径在result
操作中不再存在。我该怎么办却根本不接触数据库。
答案 0 :(得分:1)
上载的文件由应用程序存储为临时文件。这意味着一旦请求结束,临时文件将被自动删除。因此,当请求下一页时,它不再存在。
一个选择是将文件自己复制到另一个位置,并使它成为文件系统中的“真实”文件,该文件不再自动删除。但这也有缺点:现在您也有责任自己管理和删除这些文件。这意味着您需要生成唯一的文件名并将它们传递给下一个请求,并且需要确保在下载文件后删除该文件,否则这些文件将慢慢占用服务器磁盘上的所有空间。此外,它不能扩展到多台服务器,仅适用于在一台服务器上运行的小型应用程序。
更好的选择可能是仅在一个请求中执行上载,处理和下载,而无需任何重定向。只要可以在合理的时间和内存中完成处理,这可能是避免复杂性的好选择。
Stream
答案 1 :(得分:0)
尝试一下:
def upload
result(params[:csv])
end
def result(fpath=params[:file_path])
output_csv = CSV.generate do |csv|
CSV.foreach(fpath, headers: true) do |row|
csv << row
end
end
# Download the file into user's computer
send_data output_csv
end