Hochladen einer Datei in Rails

74

Ich bin neu in Rails und schreibe eine RESTful-Website mit der CRUD-Technik. Bisher habe ich drei Seiten erstellt, auf denen der Benutzer eine Zeile erstellen, bearbeiten und aus der Datenbank löschen kann. Meine vierte Seite muss jedoch ein Upload-Dateiformat enthalten. A) Ich weiß nicht, wie das Dateisystem mit Rails funktioniert, daher weiß ich nicht, wo Dateien gespeichert werden sollen. Die Datei würde ungefähr 100 KB groß sein und könnte nicht im temporären Speicher gespeichert werden, da sie ständig heruntergeladen wird. Und b) Ich weiß nicht, wie ich in eine Datei schreiben soll.

Es wäre großartig, wenn Sie mir sagen könnten, wie ich das oben erwähnte tun soll - eine Upload-Eingabe in einem Eingabeformular erstellen und die Datei dann in einen Dateipfad in einem separaten Verzeichnis schreiben.

max_
quelle

Antworten:

132

Update 2018

Während alles, was unten geschrieben steht, immer noch zutrifft, enthält Rails 5.2 jetzt auch Funktionen active_storagewie das direkte Hochladen auf S3 (oder andere Cloud-Speicherdienste), Bildtransformationen usw. Sie sollten den Rails-Leitfaden lesen und selbst entscheiden, was Ihren Anforderungen entspricht.


Während es viele Juwelen gibt, die das Hochladen von Dateien sehr gut lösen ( eine Liste finden Sie unter https://www.ruby-toolbox.com/categories/rails_file_uploads ), verfügt Rails über integrierte Helfer, mit denen Sie Ihre eigene Lösung einfach rollen können.

Verwenden Sie den file_field-form-Helfer in Ihrem Formular, und Rails übernimmt das Hochladen für Sie:

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

Sie haben im Controller Zugriff auf die hochgeladene Datei wie folgt:

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

Dies hängt von der Komplexität der gewünschten Aufgaben ab. Dies ist jedoch für einfache Aufgaben zum Hoch- und Herunterladen von Dateien völlig ausreichend. Dieses Beispiel stammt aus den Schienenführungen. Weitere Informationen finden Sie dort: http://guides.rubyonrails.org/form_helpers.html#uploading-files

fabi
quelle
3
Ich möchte die Datei jedoch nicht in die Datenbank schreiben, sondern nur in den Dateipfad. Wird der von Ihnen angegebene Code nicht in den aktiven Datensatz geschrieben?
max_
6
Nein, tatsächlich schreibt der Code es nur in das Dateisystem und überhaupt nicht in die Datenbank. Tatsächlich müssen Sie die Datei noch irgendwie mit Ihrem Datenbankeintrag verknüpfen (z. B. indem Sie den Dateinamen der hochgeladenen Datei auf die ID des Datensatzes setzen). Weitere Informationen finden Sie in der Ruby-Dokumentation unter File.open( ruby-doc.org/core-1.9.3/File.html#method-c-open ).
Fabi
7
Bitte bearbeiten Sie den zu verwendenden Code wbanstatt nur w, da sonst der Upload für Dateien mit Nicht-ASCII-Zeichen fehlschlagen kann.
Ciro Santilli 法轮功 冠状 病 六四 事件 26
Was ist in der newController-Methode?
atw
1
@KarolSelak Dieses Beispiel bietet nur einen allgemeinen Überblick über das einfache Hochladen von Dateien. Weitere Informationen zu Routing und Formularen finden Sie in den Schienenführungen ( guides.rubyonrails.org/routing.html / guide.rubyonrails.org/… )
fabi
6

September 2018

Für alle, die diese Frage kürzlich überprüft haben, verfügt Rails 5.2+ jetzt standardmäßig über ActiveStorage. Ich empfehle dringend, sie zu überprüfen.

Da es jetzt Teil der Core Rails 5.2+ ist, ist es sehr gut integriert und verfügt über hervorragende Funktionen (alle anderen bekannten Edelsteine ​​wie Carrierwave, Shrine, Büroklammer, ... sind großartig, aber dieses bietet sehr viel gute Funktionen, die wir für jedes neue Rails-Projekt berücksichtigen können)

Das Büroklammer-Team hat das Juwel zugunsten des Rails ActiveStorage abgelehnt.

Hier ist die Github-Seite für ActiveStorage und überall stehen zahlreiche Ressourcen zur Verfügung

Außerdem fand ich dieses Video sehr hilfreich, um die Funktionen von Activestorage zu verstehen

Ahmed Elkoussy
quelle
3

Besonders zum Hochladen von Dateien gibt es ein schönes Juwel: Carrierwave . Wenn das Wiki nicht hilft, gibt es eine nette RailsCast über die beste Art, es zu benutzen. Zusammenfassend gibt es filein Rails-Formularen einen Feldtyp, der den Dialog zum Hochladen von Dateien aufruft. Sie können es verwenden, aber die "Magie" wird von carrierwaveEdelstein ausgeführt.

Ich weiß nicht, was Sie mit "wie man in eine Datei schreibt" meinen, aber ich hoffe, dass dies ein guter Anfang ist.

R Milushev
quelle
Ich verstehe, also bist du mit diesem Juwel einverstanden.
R Milushev
0

In Ordnung. Wenn Sie die Datei nicht in der Datenbank und in der Anwendung speichern möchten, wie z. B. Assets (benutzerdefinierter Ordner), können Sie eine von attr_accessor: document definierte Nicht-DB-Instanzvariable definieren und zum Abrufen form_for - f.file_fieldder Datei verwenden.

In der Steuerung,

 @person = Person.new(person_params)

Hier person_paramskehren Sie auf die Whitelist zurück params[:person](definieren Sie sich selbst)

Datei speichern als,

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}")

Hinweis: Fügen Sie diesen Pfad in .gitignore& hinzu, wenn Sie diese Datei erneut verwenden möchten, und fügen Sie diesen Pfad asset_pathder Anwendung von hinzuapplication.rb

Jedes Mal, wenn ein Formular eine Datei liest, wird es im tmp-Ordner gespeichert. Später können Sie es bei Ihnen speichern. Ich habe ein Beispiel für das Speichern in Assets gegeben

Hinweis : Durch das Speichern solcher Dateien wird die Größe der Anwendung erhöht und besser in der Datenbank gespeichert paperclip.

Strahl
quelle
0

In Ihrem 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

Verwenden Sie diese Option, um sie in einer Datei zu speichern, während sie lokal ausgeführt wird

Saif Chaudhry
quelle