2009-11-04 21 views
29

Jak radzić sobie z przesyłaniem plików w kolejce bez dołączania ich do aktywnego rekordu?
Chcę tylko zapisać pliki na dysku.przesyłanie plików bez aktywnego rekordu

Dzięki,

+0

Spróbuj http://easyrails.herokuapp.com/blogs/5/upload-file-in-rails-without-model- tworzenie – vajapravin

Odpowiedz

54

Jeśli dobrze rozumiem, co trzeba wtedy najprostszym przykładem może być to:

Kontroler:

class UploadController < ApplicationController 
    def new 

    end 

    def create 
    name = params[:upload][:file].original_filename 
    path = File.join("public", "images", "upload", name) 
    File.open(path, "wb") { |f| f.write(params[:upload][:file].read) } 
    flash[:notice] = "File uploaded" 
    redirect_to "/upload/new" 
    end 
end 

Widok:

<% flash.each do |key, msg| %> 
    <%= content_tag :div, msg, :class => [key, " message"], :id => "notice_#{key}" %> 
<% end %> 
<% form_tag '/upload/create', { :multipart => true } do %> 
    <p> 
    <%= file_field_tag 'upload[file]' %> 
    </p> 
    <p> 
     <%= submit_tag "Upload" %> 
    </p> 
<% end %> 

byłoby to pozwalają przesłać dowolny plik bez żadnych sprawdzeń lub zatwierdzeń, które moim zdaniem nie są aż tak użyteczne.

Jeśli sam bym to zrobił, użyłbym czegoś takiego jak validatable gem lub tableless gem tylko tableless nie jest już obsługiwany. Te klejnoty pozwolą Ci zweryfikować to, co przesyłasz, aby było bardziej rozsądne.

+1

Upewnij się, że używasz <% = form_tag ...%> w szynach 3. – cider

+0

aby zachować spójność nie powinieneś używać 'File.join (" public "," images "," upload ")' do tworzenia 'katalogu '? – Crashalot

+0

Pewnie, to dobra wskazówka. Napisałem to naprawdę dawno temu :) Nie sądzę, żebym wiedział jak to zrobić w tym czasie :) Użyłem tylko przykładów przy kodowaniu więc w jednym wierszu go używam :)) Z drugiej strony nie. Aktualizuję teraz. –

0

Można spróbować użyć Rails plugin Attachment_fu do obsługi przesłanych plików. Umożliwia zapisywanie ładowanych plików do systemu plików zamiast do bazy danych.

+0

attachement_fu need activerecord .... – Mike

3

Dokumentacja Tempfile pokazuje przykład, który jest równoważny z kodem Rytis, który jest w porządku przez większość czasu. Ale gdy zadzwonisz pod numer tempfile.read, Ruby odczytuje cały plik jako pojedynczą porcję do pamięci, która jest nieoptymalna.

Jednak FileUtils dostarcza sposobu copy_stream i IO, przynajmniej w Ruby 2.0, zapewnia copy_stream realizację który obsługuje pisanie bezpośrednio do filePath (FileUtils.copy_stream wymaga plikopodobny obiektów po obu stronach, a przynajmniej tak mówią dokumenty).

W moim przypadku zainicjowałem duże wysyłanie wielu plików przez AJAX i chciałem uniknąć czytania całego pliku (ów) w pamięci Ruby przed zapisaniem na dysk.

W poniższym przykładzie params[:files] jest Array od ActionDispatch::Http::UploadedFile przypadkach i local_filepath jest ciągiem wskazując na nie istniejący plik w istniejącym katalogu. Dla zwięzłości, będę zakładać, mam tylko przesłać jeden plik:

IO.copy_stream(params[:files][0].tempfile, local_filepath) 

Instancja ActionDispatch::Http::UploadedFile ma .tempfile pole, które jest po prostu regularne Tempfile instancji.

Nie jestem pewien, czy Ruby wciąż nie czyta całego pliku w pamięci - nie testowałem niczego, ale jest to dużo bardziej możliwe niż w przypadku składni localfile.write(tempfile.read).

tl; dr: IO.copy_stream(your_tempfile, your_disk_filepath) jest bardziej zwięzły, jeśli nie szybszy.

4

można po prostu przenieść plik tymczasowy do ścieżki przeznaczenia przy użyciu fileutils

tmp = params[:my_file_field].tempfile 
destiny_file = File.join('public', 'uploads', params[:my_file_field].original_filename) 
FileUtils.move tmp.path, destiny_file 
Powiązane problemy