Завантаження файлу в Rails


74

Я новачок у рейлах, і пишу веб-сайт RESTful, використовуючи техніку CRUD. Наразі я створив три сторінки, всі з яких дозволяють користувачеві створювати, редагувати та видаляти рядок з бази даних. Однак моя четверта сторінка повинна містити форму файлу для завантаження, але а) Я не знаю, як файлова система працює з Rails, тому я не знаю, де слід зберігати файли. Файл складатиме близько 100 Кб, і його не можна буде зберігати у тимчасовому сховищі, оскільки він буде постійно завантажуватися. І б) Я не знаю, як писати у файл.

Було б чудово, якби ви могли сказати мені, як зробити те, про що я згадав вище - створити ввід для завантаження у форму введення, а потім записати файл у шлях до файлу в окремий каталог.

Відповіді:


132

Оновлення 2018 року

Незважаючи на те, що все, що написано нижче, все ще відповідає дійсності, Rails 5.2 тепер включає active_storage, що дозволяє завантажувати речі, такі як завантаження безпосередньо на S3 (або інші служби зберігання хмарних служб), перетворення зображень тощо. Вам слід ознайомитися з посібником із рейок і вирішити самостійно, що відповідає вашим потребам.


Незважаючи на те, що існує безліч дорогоцінних каменів, які досить добре вирішують завантаження файлів (список див. Https://www.ruby-toolbox.com/categories/rails_file_uploads ), у Rails є вбудовані помічники, які полегшують створення власного рішення.

Скористайтеся file_fieldпомічником -form у вашій формі, а Rails виконує завантаження:

<%= form_for @person do |f| %>
  <%= f.file_field :picture %>
<% end %>

Ви отримаєте доступ у контролері до завантаженого файлу таким чином:

uploaded_io = params[:person][:picture]
File.open(Rails.root.join('public', 'uploads', uploaded_io.original_filename), 'wb') do |file|
  file.write(uploaded_io.read)
end

Це залежить від складності того, чого ви хочете досягти, але цього цілком достатньо для легких завдань із завантаження / завантаження файлів. Цей приклад взятий з напрямних рейок, ви можете перейти туди для отримання додаткової інформації: http://guides.rubyonrails.org/form_helpers.html#uploading-files


3
Я не хочу писати файл у базу даних, однак, лише шлях до файлу, чи не запише код, який ви надали, до активного запису?
max_

6
ні, насправді код записує його просто у файлову систему, а не в базу даних взагалі. Насправді, вам все одно потрібно якось пов’язати файл із вашим записом бази даних (наприклад, встановивши ім’я файлу, що завантажується, ідентифікатору запису). Ви можете знайти документацію щодо рубіну для отримання додаткової інформації на File.open( ruby-doc.org/core-1.9.3/File.html#method-c-open ).
fabi

7
Будь ласка, відредагуйте код для використання, wbа не просто w, або завантаження може не вдатися для файлів із символами, які не є ascii.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Що в newметоді контролера?
atw

1
@KarolSelak у цьому прикладі якраз наводяться загальні схеми простих завантажень файлів. Ви можете дізнатись більше про маршрутизацію та форми у напрямних рейок ( guides.rubyonrails.org/routing.html / guides.rubyonrails.org/… )
fabi

6

Вересень 2018

Для тих, хто перевіряв це питання нещодавно, Rails 5.2+ тепер має ActiveStorage за замовчуванням, і я настійно рекомендую перевірити його.

Оскільки зараз він є частиною основного Rails 5.2+, він дуже добре інтегрований і має чудові можливості нестандартно (все-таки всі інші відомі дорогоцінні камені, такі як Carrierwave, Shrine, скріпка, ... чудові, але цей пропонує дуже хороші можливості, які ми можемо розглянути для будь-якого нового проекту Rails)

Команда скріпок припинила дорогоцінний камінь на користь Rails ActiveStorage.

Ось сторінка github для ActiveStorage, і багато ресурсів доступні скрізь

Також я знайшов це відео дуже корисним для розуміння особливостей Activestorage


3

Існує приємний камінь, особливо для завантаження файлів: carrierwave . Якщо вікі не допомагає, є приємний RailsCast про найкращий спосіб її використання. Підсумовуючи, fileу формах Rails є тип поля , який викликає діалогове вікно завантаження файлу. Ви можете ним скористатися, але "магія" виконуєтьсяcarrierwave самоцвіт.

Не знаю, що ви маєте на увазі під словом "як записати у файл", але сподіваюся, це хороший початок.


Я розумію, тобі з цим gem все в порядку.
Р Мілушев

0

Добре. Якщо ви не хочете зберігати файл у базі даних і зберігати в програмі, як-от активи (спеціальна папка), ви можете визначити змінну екземпляра не-db, визначену attr_accessor: document і використовувати form_for - f.file_fieldдля отримання файлу,

У контролері,

 @person = Person.new(person_params)

Тут person_paramsповерніть у білий списокparams[:person] (визначтесь самі)

Зберегти файл як,

dir = "#{Rails.root}/app/assets/custom_path"
FileUtils.mkdir(dir) unless File.directory? dir
document = @person.document.document_file_name # check document uploaded params
File.copy_stream(@font.document, "#{dir}/#{document}")

Примітка. Додайте цей шлях до .gitignore&, якщо ви хочете знову використовувати цей файл, додайте цей шлях asset_pathдо програми за допомогоюapplication.rb

Щоразу, коли форма читає поле файлу, вона отримує store у папці tmp, пізніше ви можете зберігати її у себе, я наводив приклад для зберігання в активах

Примітка . Зберігання подібних файлів збільшить розмір програми, краще зберігати її в базі даних paperclip.


0

У вашому intiallizer / carrierwave.rb

if Rails.env.development? || Rails.env.test?
    config.storage = :file
    config.root = "#{Rails.root}/public"
    if Rails.env.test?
      CarrierWave.configure do |config|
        config.storage = :file
        config.enable_processing = false
      end
    end
 end

використовуйте це для зберігання у файлі під час запуску на локальному

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.