Restricting size of an uploaded file, is how is that possible? If I do not want a user to upload a file larger than X bytes, can it easily be done? If I also would like restrict the types of files that can be uploaded, how may I do so? Thank you, Sharkie
file_column from trunk has optional file_size validation. AFAIK, validation is done before saving, in that case, you are still uploading the file. A better option would be if the webserver would cancel the upload, when the max filesize is reached. I am using Lighttpd, which has no such upload mod, but maybe apache has some some ? Or try to convince Zed<http://www.zedshaw.com/>to put some sophisticated upload functionality into mongrel. Filetype can be restricted with a bit of javascript and regular expression when the Input field of the File upload form changes. This<http://blog.caboo.se/articles/2006/02/23/integrate-rails-modules-with-javascript-objects>might help you to understand how you need to aproach that. Or if you like flash, you can rely on flashplayer 8 for highly configurable file-upload (with smooth progress indicator), but that wil require a lot of Javascript for the integration. On 3/4/06, Shark Fin Soup <shark.fin.soup@mac.com> wrote:> > Restricting size of an uploaded file, is how is that possible? If I > do not want a user to upload a file larger than X bytes, can it > easily be done? > > If I also would like restrict the types of files that can be > uploaded, how may I do so? > > Thank you, > > Sharkie > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Roberto Saccon - http://rsaccon.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060304/aec38689/attachment.html
Shark Fin Soup wrote:> Restricting size of an uploaded file, is how is that possible? If I > do not want a user to upload a file larger than X bytes, can it > easily be done? > > If I also would like restrict the types of files that can be > uploaded, how may I do so?You should be able to write a conditional using rmagick''s image.filesize attribute: http://www.simplesystems.org/RMagick/doc/imageattrs.html#filesize Same goes for the format with the image.format attribute: http://www.simplesystems.org/RMagick/doc/imageattrs.html#format -- Posted via http://www.ruby-forum.com/.
Roberto Saccon wrote:> > Filetype can be restricted with a bit of javascript and regular > expression when the Input field of the File upload form changes. This > <http://blog.caboo.se/articles/2006/02/23/integrate-rails-modules-with-javascript-objects> > might help you to understand how you need to aproach that. Or if you > like flash, you can rely on flashplayer 8 for highly configurable > file-upload (with smooth progress indicator), but that wil require a > lot of Javascript for the integration. >Very bad idea...dont think you can secure any application with JS touching/limiting the input / form etc..any kid could still use its very own form to upload files without any of your fuzzy JS and you wouldnt have won anything....that might just help as an additional feature but is anything but secure...also headerdata can be changed easily, so there is no way to prevent someone to use his OWN forms to upload stuff, that said, any serious validation can only be done serverside. This is a general rule and belongs to every kind of userdata, not just uploaded images... Greez Matthias Oesterle
Matthias, of course you are right. I should have mentioned that any kind of client side validation also needs a serverside validation. Clientside validation is not for securing the app, it is to improve usability and responsiveness of the app. On 3/4/06, matthibcn <matthibcn@gmail.com> wrote:> > Roberto Saccon wrote: > > > > > Filetype can be restricted with a bit of javascript and regular > > expression when the Input field of the File upload form changes. This > > < > http://blog.caboo.se/articles/2006/02/23/integrate-rails-modules-with-javascript-objects > > > > might help you to understand how you need to aproach that. Or if you > > like flash, you can rely on flashplayer 8 for highly configurable > > file-upload (with smooth progress indicator), but that wil require a > > lot of Javascript for the integration. > > > Very bad idea...dont think you can secure any application with JS > touching/limiting the input / form etc..any kid could still use its very > own form to upload files without any of your fuzzy JS and you wouldnt > have won anything....that might just help as an additional feature but > is anything but secure...also headerdata can be changed easily, so there > is no way to prevent someone to use his OWN forms to upload stuff, that > said, any serious validation can only be done serverside. > > This is a general rule and belongs to every kind of userdata, not just > uploaded images... > > Greez > > Matthias Oesterle > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Roberto Saccon - http://rsaccon.com -------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060304/555f9349/attachment-0001.html
Roberto Saccon wrote:> Matthias, of course you are right. I should have mentioned that any > kind of client side validation also needs a serverside validation. > Clientside validation is not for securing the app, it is to improve > usability and responsiveness of the app. >Absolutly, Roberto, thats the point: it aids in usability and is a nice feature Anyway back to the topic: I am also in the same need as the starter and remember that after spending just a couple of minutes (30, 40, 50..dont remember) some days ago I wasnt able to find any (direct) solution, so I still hope that someone could answer that. Probably one has to spend hours beeing new to RMagick and friends,what I definatly will do if its coming to that point, but I was also looking for something like image.width /.height and couldnt find any solution...this is needed to have a popup sized dynamically to the "right" size if I click of one of my thumbnails, as its a big different dealing with portrait/landscape imageformats..... Regards Matthias Oesterle
Hi, a) there is a modification of file_column from kyle: http://opensvn.csie.org/rails_file_column/plugins/file_column/ have a look at http://opensvn.csie.org/rails_file_column/plugins/file_column/trunk/lib/validations.rb It validates filesizes and extensions. b) Sebastian, the founder of file_column, annouced an update ("with lots of goodies") soon: http://www.kanthak.net/explorations/blog/rails/canada_on_rails.html Beate
Joe Block wrote:> Berin, > > You mentioned on the Rails list that you had some sample code for > embedding files into a MySQL db you were willing to share - could I > get a copy? I''m a n00b to Rails and I have a project in the works that > may need to do exactly that.Sure thing. For my case, I have a Projects class to manage my projects, and they all have an icon. So lets start out with the DB Migration (assuming you are using Rails 1.0?) class Projects < ActiveRecord::Migration def self.up create_table :projects, :force => true do |t| t.column :name, :string, :default => "", :null => false t.column :description, :string t.column :content_type, :string, :default => "image/png" t.column :icon, :binary end logo = File.new("db/dhaven.gif", "rb") dhaven = Project.new dhaven.name = "D-Haven" dhaven.description = "The D-Haven infrastructure" dhaven.content_type = "image/gif" dhaven.icon = logo.read dhaven.save end def self.down drop_table :projects end end In the creation part, I create my table with a column for the file mime-type called "content-type" (your HTTP name for the mime-type) and a column for the data itself called "icon". The next set of lines pre-populates the table with one record. Please note that if you are going to prepopulate your tables you have to open your file as a binary: File.new("db/dhaven.gif", "rb"). The "rb" is very important, or the image will truncate at the first byte that is a zero. Next, we need to create our model: class Project < ActiveRecord::Base validates_format_of :content_type, :with => /^image/, :message => "You can only upload pictures" def iconimg=(picture_field) self.content_type = picture_field.content_type.chomp self.icon = picture_field.read end end I added some logic here to enforce only images (mime-types that start with "image/". Just as important, I create a "psuedo-field" to work with the forms. When you get the uploaded file from the form, it has an object that has both the content_type and the binary data (it is already binary format). The upload field will be named "iconimg". I''m going to shorten my controller so that you can see how to populate the fields to save it, and how to display the stored image. Everything else is up to you: class ProjectsController < ApplicationController layout ''site'' def update @project = Project.find(params[:id]) if @project.update_attributes(params[:project]) flash[:notice] = ''Project was successfully updated.'' redirect_to :action => ''show'', :id => @project else redirect_to :action => ''edit'' end end def icon @project = Project.find(params[:id]) send_data(@project.icon, :type => @project.content_type, :disposition => "inline") end end In the update() action, everything looks the same as it always was. To update a project, you call the update_attributes(params[:project]) and to create a new project you call the Project.new(params[:project]) method. To display the saved information, you have to use the send_data() call. The method finds the object you need (in my case a project), and then sends the binary data and the content_type. From the controller standpoint, we are done. Lastly, you have to set up your form correctly. Here are some important key elements: <%= form_tag({:action => ''create''}, :multipart => true) %> <p><label for="project_name">Name</label><br/> <%= text_field ''project'', ''name'' %></p> <p><label for="project_description">Description</label><br/> <%= text_area ''project'', ''description'' %> <p><label for="project_icon">Icon</label><br/> <%= file_field ''project'', ''iconimg'' %> </p> <%= submit_tag "Create" %> <%= end_form_tag %> Your form must be multipart, so use the form tag above. Next, use the <%= file_field ''project'', ''iconimg'' %> to upload the file. This is the psuedofield you created in the model. Lastly, I created a couple of helpers to let me show the image and create links. For completeness sake it is here: module ProjectsHelper def url_for_icon( project ) url_for(:controller => ''projects'', :action => ''icon'', :id => project.id) end def icon_image_tag( project ) "<img alt=\"#{project.name}\" src=\"#{url_for_icon project}\"/>" end def link_icon_to( project ) project_url = url_for(:controller => ''projects'', :action => ''show'', :id => project.id) "<a href=\"#{project_url}\">#{icon_image_tag project}</a>" end end If you have any questions, comments, suggestions, etc. Don''t hesitate to ask.
Thank you Berin for posting your code for storing, serving, and uploading images to/from the database. Is there any easy way to automatically cache images sent from the database, so that the web server rather than Rails & the DB will eventually process the hits, or would this have to be written as an extention to the file_column plugin? -- We develop, watch us RoR, in numbers too big to ignore.
Mark Reginald James wrote:> Thank you Berin for posting your code for storing, serving, and uploading > images to/from the database. Is there any easy way to automatically > cache images sent from the database, so that the web server rather than > Rails & the DB will eventually process the hits, or would this have to be > written as an extention to the file_column plugin? >To be honest I wouldn''t know. I''m pretty new to rails too. I haven''t done anything with caching yet. I do know that if you stick a proxy server in front of everything you have more options for caching (like squid).
Berin Loritsch wrote:> Mark Reginald James wrote: >> Thank you Berin for posting your code for storing, serving, and >> uploading >> images to/from the database. Is there any easy way to automatically >> cache images sent from the database, so that the web server rather than >> Rails & the DB will eventually process the hits, or would this have >> to be >> written as an extention to the file_column plugin? >> > To be honest I wouldn''t know. I''m pretty new to rails too. I haven''t > done anything with caching yet. I do know that if you stick a proxy > server in front of everything you have more options for caching (like > squid).Ok, I take that back. There are HTTP headers you can apply that control browser caching. I don''t know them off the top of my head (most of the tools I''ve used take care of it for me). Googling on HTTP cache directives will tell you what to set. The code that renders the image could also be enhanced by examining the request header. If the browser has a "modified-since" header with a timestamp, and the image hasn''t changed you retern a 202 code which tells the browser to use the cached version.
Berin, Thanks for sharing your code... I am going to tackle a project that requires icons soon. I''m thinking that I will store image files in the filesystem to allow for lighttpd to serve these ultra-fast without hitting the db for each one. If anyone has code snippets along these lines let me know :) or I''ll post my code when I get it worked out. Thanks, Zack On 3/6/06, Berin Loritsch <bloritsch@d-haven.org> wrote:> > Joe Block wrote: > > Berin, > > > > You mentioned on the Rails list that you had some sample code for > > embedding files into a MySQL db you were willing to share - could I > > get a copy? I''m a n00b to Rails and I have a project in the works that > > may need to do exactly that. > > Sure thing. For my case, I have a Projects class to manage my projects, > and they all have an icon. So lets start out with the DB Migration > (assuming you are using Rails 1.0?) > > class Projects < ActiveRecord::Migration > def self.up > create_table :projects, :force => true do |t| > t.column :name, :string, :default => "", :null => false > t.column :description, :string > t.column :content_type, :string, :default => "image/png" > t.column :icon, :binary > end > > logo = File.new("db/dhaven.gif", "rb") > dhaven = Project.new > dhaven.name = "D-Haven" > dhaven.description = "The D-Haven infrastructure" > dhaven.content_type = "image/gif" > dhaven.icon = logo.read > dhaven.save > end > > def self.down > drop_table :projects > end > end > > > In the creation part, I create my table with a column for the file > mime-type called "content-type" (your HTTP name for the mime-type) and a > column for the data itself called "icon". The next set of lines > pre-populates the table with one record. Please note that if you are > going to prepopulate your tables you have to open your file as a binary: > File.new("db/dhaven.gif", "rb"). The "rb" is very important, or the > image will truncate at the first byte that is a zero. > > Next, we need to create our model: > > class Project < ActiveRecord::Base > validates_format_of :content_type, :with => /^image/, > :message => "You can only upload pictures" > > def iconimg=(picture_field) > self.content_type = picture_field.content_type.chomp > self.icon = picture_field.read > end > end > > I added some logic here to enforce only images (mime-types that start > with "image/". Just as important, I create a "psuedo-field" to work > with the forms. When you get the uploaded file from the form, it has an > object that has both the content_type and the binary data (it is already > binary format). The upload field will be named "iconimg". > > I''m going to shorten my controller so that you can see how to populate > the fields to save it, and how to display the stored image. Everything > else is up to you: > > class ProjectsController < ApplicationController > layout ''site'' > > def update > @project = Project.find(params[:id]) > if @project.update_attributes(params[:project]) > flash[:notice] = ''Project was successfully updated.'' > redirect_to :action => ''show'', :id => @project > else > redirect_to :action => ''edit'' > end > end > > def icon > @project = Project.find(params[:id]) > send_data(@project.icon, > :type => @project.content_type, > :disposition => "inline") > end > end > > In the update() action, everything looks the same as it always was. To > update a project, you call the update_attributes(params[:project]) and > to create a new project you call the Project.new(params[:project]) > method. To display the saved information, you have to use the > send_data() call. The method finds the object you need (in my case a > project), and then sends the binary data and the content_type. From the > controller standpoint, we are done. > > Lastly, you have to set up your form correctly. Here are some important > key elements: > > <%= form_tag({:action => ''create''}, :multipart => true) %> > > <p><label for="project_name">Name</label><br/> > <%= text_field ''project'', ''name'' %></p> > > <p><label for="project_description">Description</label><br/> > <%= text_area ''project'', ''description'' %> > > <p><label for="project_icon">Icon</label><br/> > <%= file_field ''project'', ''iconimg'' %> > </p> > > <%= submit_tag "Create" %> > <%= end_form_tag %> > > Your form must be multipart, so use the form tag above. Next, use the > <%= file_field ''project'', ''iconimg'' %> to upload the file. This is the > psuedofield you created in the model. > > Lastly, I created a couple of helpers to let me show the image and > create links. For completeness sake it is here: > > module ProjectsHelper > def url_for_icon( project ) > url_for(:controller => ''projects'', :action => ''icon'', :id => > project.id) > end > > def icon_image_tag( project ) > "<img alt=\"#{project.name}\" src=\"#{url_for_icon project}\"/>" > end > > def link_icon_to( project ) > project_url = url_for(:controller => ''projects'', :action => ''show'', > :id => project.id) > "<a href=\"#{project_url}\">#{icon_image_tag project}</a>" > end > end > > If you have any questions, comments, suggestions, etc. Don''t hesitate > to ask. > > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-------------- next part -------------- An HTML attachment was scrubbed... URL: http://wrath.rubyonrails.org/pipermail/rails/attachments/20060307/d0de9795/attachment.html
Zack Chandler wrote:> Berin, > Thanks for sharing your code... I am going to tackle a project that > requires icons soon. I''m thinking that I will store image files in > the filesystem to allow for lighttpd to serve these ultra-fast without > hitting the db for each one. If anyone has code snippets along these > lines let me know :) or I''ll post my code when I get it worked out.If you are using the filesystem, I highly recommend the file upload plugin. It provides helpers to do AJAX uploads (upload with a progress bar, and then display in place). It works strictly with the filesystem, and it integrates with ImageMagick so you can resize or transform your icons. The only reason I''m not using it is because I wanted to store the images in the database.
Berin Loritsch wrote:> Berin Loritsch wrote: >> Mark Reginald James wrote: >>> Is there any easy way to automatically >>> cache images sent from the database, so that the web server rather than >>> Rails & the DB will eventually process the hits, or would this have >>> to be >>> written as an extention to the file_column plugin? > > Ok, I take that back. There are HTTP headers you can apply that control > browser caching. I don''t know them off the top of my head (most of the > tools I''ve used take care of it for me). Googling on HTTP cache > directives will tell you what to set. > > The code that renders the image could also be enhanced by examining the > request header. If the browser has a "modified-since" header with a > timestamp, and the image hasn''t changed you retern a 202 code which > tells the browser to use the cached version.I wasn''t referring to browser or proxy caching, but to Rails'' page and action caching. It''d be good if you could do some experiments with your code to see if Rails will properly cache the images in files so that either the http server can serve them without touching Rails (page caching -- http://api.rubyonrails.com/classes/ActionController/Caching/Pages.html ) or Rails is hit but no DB access is needed (action caching -- http://api.rubyonrails.com/classes/ActionController/Caching/Actions.html ). -- We develop, watch us RoR, in numbers too big to ignore.