Загрузить, обработать и экспортировать CSV без базы данных - PullRequest
0 голосов
/ 25 октября 2018

Я создаю очень простой веб-инструмент, в котором пользователь может загрузить файл 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.Как я могу сделать это, не касаясь БД вообще.

Ответы [ 2 ]

0 голосов
/ 25 октября 2018

Загруженные файлы сохраняются приложением в виде временных файлов.Это означает, что после завершения запроса временный файл автоматически удаляется.Поэтому он больше не существует, когда запрашивается следующая страница.

Один из вариантов - скопировать файл самостоятельно в другое место и сделать его «настоящим» файлом в файловой системе, который не был удален.автоматически больше.Но это тоже имеет свои недостатки: теперь вы сами отвечаете за управление и удаление этих файлов.Это означает, что вам нужно сгенерировать уникальные имена файлов и передать их следующему запросу, а также убедиться, что файл удален после его загрузки, в противном случае эти файлы будут медленно занимать все пространство на диске вашего сервера.Кроме того, это не масштабируется до нескольких серверов и будет работать только для небольших приложений, работающих на одном сервере.

Лучшим вариантом может быть просто выполнить загрузку, обработку и загрузку в одном запросе без какого-либо перенаправления.Пока обработка может быть выполнена в разумные сроки и в памяти, это может быть хорошим вариантом, чтобы избежать сложности.

def upload
  original_csv = params[:csv]

  output_csv = CSV.generate do |csv|
    CSV.foreach(original_csv.path, headers: true) do |row|
      # process data
      csv << row
    end
  end

  send_data output_csv
end
0 голосов
/ 25 октября 2018

Попробуйте это:

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
...