I'm using shrine to upload files from my rails application to S3. All is working fine, but I dont know how to display that file using redcarpet gem.
For example I can do this:
<div>
<%= markdown("##title
* ") %>
</div>
And works fine.
But if I do this:
<%= markdown(#rfile.rfile.url) %>
Is showing me a download link from S3.
How I can get the file content and not the file link?
Call to #rfile.rfile returns a Shrine::UploadedFile object, which has many more convenient methods other than just #url. On such method is #read, which retrieves content of the file:
<%= markdown(#rfile.rfile.read) %>
However, in this case the file would be opened and read, but not closed. So it's better to call #open with a block, and call #read on the yielded IO object, which can be neatly written as
<%= markdown(#rfile.rfile.open(&:read)) %>
Related
I'm trying to use smarter_csv to parse csv files with my Rails app. But the documentation only explains how to parse a file that already belongs to the app.
I want to parse a file that's stored locally on my computer. So I think I have to upload the file, parse it, and then delete it.
This is how far I got:
<%= form_tag({action: :upload}, multipart: true) do %>
<%= file_field :csv %>
<%= submit_tag 'Submit' %>
<% end %>
So then how can I reference and use the uploaded file in my controller action?
def upload
#save file temporarily to app
filename = #filename
#parse file with smarter_csv
#File.delete(filename)
end
To get the file path as a string you need to do the following:
filename = params[:csv].path
as params[:csv] is a UploadedFile object. You don't need handle the temp file yourself, i.e. storing and deleting it. Rails would do that for you. As per documentation:
Uploaded files are temporary files whose lifespan is one request. When the object is finalized Ruby unlinks the file, so there is no need to clean them with a separate maintenance task.
I am developing a tool which uploads a file to Google Drive. I am using 'google-drive' gem.
In my view I have taken it as
<%= file_field :file, class: 'form-control' %> <br>
I call a method in controller for form which passes the params[:file]
session = GoogleDrive::Session.from_config("config.json")
session.upload_from_file(params[:file], "right-on.txt", convert: false)
but on submit I get -
no implicit conversion of ActionController::Parameters into String.
How do I successfully pass the file to be uploaded to Google Drive. If I pass a local file path instead of params[:file], file gets uploaded sucessfully. I have to do it with file selection.
If you inspect your file upload input tag in the web console, you will see something like this:
<input type="file" name="file[{:class=>"form-control"}]" id="file_{:class=>"form-control"}">
If you open the documentation for the file_field method, you will notice that it accepts first an object name, then a method and last options, such as class: 'form-control'.
I guess you would want to do something like this inside your view:
<%= file_field :drive, :file, class: 'form-control' %>
This will generate HTML tag like this:
<input class="form-control" type="file" name="drive[file]" id="drive_file">
Then you can upload the file in your controller like you already do.
Check if multipart is set to 'true' in the form tag.
If not, set it true.
and instead of passing params[:file], pass params[:file].path.to_s
the upload function is expecting a string as a path. params[:file] is actually a file itself which gets stored in temp folder while uploading. Check once without using to_s.
This should help.
I am using Ruby on Rails 3 and in a my view file I have this code:
<%= form_for (#account, ...) do |f| %>
<%= f.file_field :file %>
...
<%= f.submit "Upload" %>
<% end %>
In order to avoid an overloading of the server, I would check the size of the uploading file before that the server receives it. This is because, pressing the submit button of the form, the server first will entirely receive the file and after will check the file.
I know that a HTTP request has header fields, so I would like to check those for the uploading file, in particular, in my case, the Content-Length value.
How to do that?
Did you try request.headers["content-length"] ?
Doesn't nginx set a max file size too? Using that as your 'base' you can assure that the server will stop a big ass file upload. Maybe set it to the same max size if you are worried about this.
I'm using Rails 3 paperclip and allow users to upload attachments to the attachment model.
If the file is an image, the app generates image previews. If the file is not, it only uploads the file (no image previews).
Now I would like to display a list of all the attachments in the DB. So I use attachment.attachment(:large) and that works fine for image attachments, but errors (obviously) for non-image attachments.
What's a good way to check if it's an image attachment or not? If not, I'd like to display a standard static image. Any suggestions? thanks
This is what I did in my view:
<% if !(#attachment.attachment.content_type =~ /^image/).nil? %>
<%= image_tag #attachment.attachment.url(:small) %>
<%end%>
This assumes that your model is attachment, and my file, I so called attachment.
So you could do something like:
<% if !(#attachment.attachment.content_type =~ /^image/).nil? %>
<%= image_tag #attachment.attachment.url(:small) %>
<%else%>
<%= image_tag "/path/to/image/default.png" %>
<%end%>
Check attachment.attachment.attachment_content_type
For example, it might be: "image/jpeg"
You can create a migration that adds a attachment_content_type field of type string to your attachment table. When you create an attachment, paperclip stores the type of the file in that field. You can then check if the file type is something like "image/jpeg".
Maybe you could use default_url option? That would be shown if the real thumbnail doesn't exist.
http://www.suffix.be/blog/default-image-paperclp
How do you handle file upload in rail without attaching them to active record ?
I just want to write the files to the disk.
Thanks,
If I understand correctly what you need then the most simple example would be this:
The controller:
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
The view:
<% 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 %>
This would let you upload any file without any checks or validations which in my opinion isn't that usefull.
If I would do it myself then I would use something like validatable gem or tableless gem just tableless is not supported anymore. These gems would allow you to validate what you're uploading to make it more sane.
You can just move the temporary file to destiny path using 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
The Tempfile documentation shows an example that's equivalent to Rytis's code, which is fine most of the time. But when you call tempfile.read, Ruby is reading the whole file as a single chunk into memory, which is sub-optimal.
However, FileUtils provides a copy_stream method, and IO, at least in Ruby 2.0, provides a copy_stream implementation that handles writing directly to a filepath (FileUtils.copy_stream requires File-like objects on both sides, or so say the docs).
In my case, I was initiating a large multi-file upload via AJAX, and wanted to avoid reading the whole file(s) into Ruby's memory before writing to disk.
In the example below, params[:files] is an Array of ActionDispatch::Http::UploadedFile instances, and local_filepath is a string pointing to a non-existing file in an existing directory. For brevity, I'll assume I'm only uploading one file:
IO.copy_stream(params[:files][0].tempfile, local_filepath)
The ActionDispatch::Http::UploadedFile instance has a .tempfile field that's just a regular Tempfile instance.
I'm not actually sure that Ruby still isn't reading the whole file into memory—I didn't benchmark anything—but it's a lot more possible than it is with the localfile.write(tempfile.read) syntax.
tl;dr: IO.copy_stream(your_tempfile, your_disk_filepath) is more concise, if not faster.
You could try using the Rails plugin Attachment_fu to handle file uploads. It allows you to save uploads to the file system instead of the database.