Ruby on Rails 2.1 - Upload de arquivo
Você pode ter um requisito no qual deseja que os visitantes do site carreguem um arquivo em seu servidor. Rails torna muito fácil lidar com esse requisito. Agora, prosseguiremos com um projeto Rails simples e pequeno.
Como de costume, vamos começar com um novo aplicativo Rails chamado upload. Vamos criar uma estrutura básica do aplicativo usando o comando rails simples.
C:\ruby> rails -d mysql upload
Vamos decidir onde você gostaria de salvar seus arquivos carregados. Suponha que sejadatadiretório dentro de sua seção pública. Portanto, crie este diretório e verifique as permissões.
C:\ruby> cd upload
C:\ruby\upload> mkdir upload\public\data
Nosso próximo passo será, como de costume, criar controlador e modelos.
Criando o modelo
Como este não é um aplicativo baseado em banco de dados, podemos manter qualquer nome que seja confortável para nós. Suponha que temos que criar umDataFile modelo.
C:\ruby\upload> ruby script/generate model DataFile
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/data_file.rb
create test/unit/data_file_test.rb
create test/fixtures/data_files.yml
create db/migrate
create db/migrate/001_create_data_files.rb
Agora, vamos criar um método chamado save dentro data_file.rbarquivo de modelo. Este método será chamado pelo controlador de aplicativo.
class DataFile < ActiveRecord::Base
def self.save(upload)
name = upload['datafile'].original_filename
directory = "public/data"
# create the file path
path = File.join(directory, name)
# write the file
File.open(path, "wb") { |f| f.write(upload['datafile'].read) }
end
end
A função acima irá pegar o objeto CGI upload e irá extrair o nome do arquivo enviado usando a função auxiliar original_filenamee, finalmente, armazenará o arquivo carregado no diretório "public / data". Você pode chamar a função auxiliarcontent_type para saber o tipo de mídia do arquivo carregado.
Aqui File é um objeto rubi e join é uma função auxiliar que concatenará o nome do diretório junto com o nome do arquivo e retornará o caminho completo do arquivo.
Em seguida, para abrir um arquivo no modo de gravação, estamos usando a função open helper fornecida pelo Fileobjeto. Além disso, estamos lendo dados do arquivo de dados transmitidos e gravando no arquivo de saída.
Criando controlador
Agora, vamos criar um controlador para nosso projeto de upload -
C:\ruby\upload> ruby script/generate controller Upload
exists app/controllers/
exists app/helpers/
create app/views/upload
exists test/functional/
create app/controllers/upload_controller.rb
create test/functional/upload_controller_test.rb
create app/helpers/upload_helper.rb
Agora, vamos criar duas funções de controlador. A primeira funçãoindex irá chamar um arquivo de visualização para obter a entrada do usuário, e a segunda função uploadFilepega as informações do arquivo do usuário e as passa para o modelo 'DataFile'. Definimos o diretório de upload para o diretório 'uploads' que criamos anteriormente "directory = 'data'".
class UploadController < ApplicationController
def index
render :file => 'app\views\upload\uploadfile.html.erb'
end
def uploadFile
post = DataFile.save( params[:upload])
render :text => "File has been uploaded successfully"
end
end
Aqui, estamos chamando a função definida no arquivo de modelo. orender função está sendo usada para redirecionar para visualizar o arquivo, bem como para exibir uma mensagem.
Criando vista
Finalmente, vamos criar um arquivo de visão uploadfile.rhtml,que mencionamos no controlador. Preencha este arquivo com o seguinte código -
<h1>File Upload</h1>
<% form_tag ({:action => 'uploadFile'},
:multipart => true) do %>
<p><label for="upload_file">Select File</label> :
<%= file_field 'upload', 'datafile' %></p>
<%= submit_tag "Upload" %>
<% end %>
Aqui tudo é igual ao que explicamos nos capítulos anteriores. A única nova tag éfile_field, que criará um botão para selecionar um arquivo do computador do usuário.
Ao definir o parâmetro multipart como true, você garante que sua ação transmita corretamente os dados binários do arquivo.
Aqui, um ponto importante a observar é que atribuímos "uploadFile" como o nome do método em :action, que será chamado quando você clicar no Upload botão.
Ele irá mostrar a você uma tela como a seguir -
Agora, você seleciona um arquivo e carrega-o. Este arquivo será carregado no diretório app / public / data com o nome do arquivo real e uma mensagem será exibida dizendo que "Arquivo foi carregado com sucesso"
NOTE - Se um arquivo com o mesmo nome já existir em seu diretório de saída, ele será sobrescrito.
Arquivos enviados do Internet Explorer
O Internet Explorer inclui todo o caminho de um arquivo no nome do arquivo enviado, portanto, original_filename rotina retornará algo como -
C:\Documents and Files\user_name\Pictures\My File.jpg
Em vez de apenas -
My File.jpg
Isso é facilmente resolvido por File.basename, que remove tudo antes do nome do arquivo.
def sanitize_filename(file_name)
# get only the filename, not the whole path (from IE)
just_filename = File.basename(file_name)
# replace all none alphanumeric, underscore or perioids
# with underscore
just_filename.sub(/[^\w\.\-]/,'_')
end
Excluindo um arquivo existente
Se você deseja excluir qualquer arquivo existente, é muito simples. Tudo o que você precisa fazer é escrever o seguinte código -
def cleanup
File.delete("#{RAILS_ROOT}/dirname/#{@filename}")
if File.exist?("#{RAILS_ROOT}/dirname/#{@filename}")
end
Para um detalhe completo sobre File objeto, você precisa passar por nosso Ruby Reference Manual.