如何将选定的文件名传递给控制器​​以在 Rails 中进行处理

How to pass selected filename to controller to process in Rails

我想 select 本地计算机上的一个 zip 文件并在添加到数据库之前对其进行处理。

除了传入文件名外,我已经让控制器完成所有这些工作。如果我手动输入文件名就可以了。

<%= form_with model: @bp, url: { action: "import_data" } do |form| %>
  <%= form.file_field :health_exported_zip %>
  <%= submit_tag( "Import" ) %>
<% end %>

bp_controller

def import_data
  # Following line errors
  health_exported_zip_file = params[:health_exported_zip] # no implicit conversion of nil into String
  # Manually setting file location which works with the above line commented out
  health_exported_zip_file = "/Users/username/Downloads/export.zip"
  unzip_import_data(health_exported_zip_file)
  …
end

def unzip_import_data(health_exported_zip_file)
  require 'zip'
  unzip_to =  "import_staging"
  …
end

# Only allow a list of trusted parameters through.
def bp_params
  params.require(:bp).permit(:statdate, :systolic, :diastolic, :heartrate, :sourceName, :sourceVersion, :comment, :health_exported_zip)
end

这个做起来一定很简单,但是我很茫然。使用类似 form_with 的 ActiveStorage 在文件上传时必须有权访问该文件。谢谢

如此不简单,但@masasakano 指出我阅读了 params,我按如下方式解析它以获取 zip 文件的临时副本的路径。

indexTempfile = params.to_s.index('/var/folders') # setting start of Tempfile location
tempfile_path = params.to_s.slice!(indexTempfile..450) # slice off the beginning of params
indexEnd = tempfile_path.to_s.index('>') - 1 # get end of Tempfile location. 
tempfile_path = tempfile_path.to_s.slice!(0..indexEnd) # slice off the end of params and left with path

tempfile_pathhealth_exported_zip_file 所需要的。已重命名,因为它不是原始文件。

什么 params returns 是一个 ActionDispatch::Http::UploadedFile object (see Official reference)。因此 params 的 returned 值是 而不是 您用 unzip_import_data(health_exported_zip_file).

手动设置的文件名

相反,您可以使用 params[:bp][:health_exported_zip].pathparams[:bp][:health_exported_zip].tempfile.path 的别名)获取上传文件的路径,您可以将其提供给解压缩功能。

所以,这是我注意到的一个问题。

但是,如果您遇到的异常是no implicit conversion of nil into String,那么我猜params首先未能提取上传的文件,然后params[:bp][:health_exported_zip] returns nil。有很多潜在的原因,例如,您实际上没有上传文件(即使您认为您上传了),或者上传的文件超过了最大允许大小,或者没有从视图调用控制器如您所愿,等等……

我的建议是在您的特定情况下转储 params 以查看传递给您的控制器的内容作为您调查的起点。

[编辑]
交换意见后发现,Controller中包含的OP的预过滤方法是not在OP的测试用例中调用的。然后,由于 Rail 的强参数约束,health_exported_zipparams 中过滤掉,params[:bp][:health_exported_zip] 将 return nil。因此,您应该在 before_actiononly 子句中添加 :import_data 以调用预处理方法。或者,更直接的方法是在 import_data 方法的开头添加您选择的 params.permit 等行。