Upload только файлов jpg

5 views
Skip to first unread message

Denis Surkov

unread,
Oct 3, 2006, 6:18:32 AM10/3/06
to ror...@googlegroups.com
Как можно реализовать сабж? Пока использую такое:

во View:

<%= start_form_tag({:action => "save_user"}, :multipart => true) %>
Photo:
<%= file_field("user", "photofile") %>
<%= end_form_tag %>

в контроллере:

def save_user
pfile = params[:user][:photofile]
if pfile.original_filename.size > 0
File.open("#{RAILS_ROOT}/public/images/photo/photo1.jpg", "wb") do |f|
f.write(pfile.read)
end
end
end

Но это просто аплоад файлов. А надо аплоадить только картинки jpg. Как
задать такое условие?

--
С уважением, Den
icq# 301033169

Maxim Kulkin

unread,
Oct 3, 2006, 6:45:34 AM10/3/06
to ror...@googlegroups.com
On 3 October 2006 14:18, Denis Surkov wrote:
> Но это просто аплоад файлов. А надо аплоадить только картинки jpg. Как
> задать такое условие?
На стороне клиента можно только жаваскриптом значение input'а проверить на
предмет правильного расширения файла. А на сервере можно получить mime-тип
файла (если на *nix - утилита "file", или использовать gem mime-types).

Sergey Kojin

unread,
Oct 3, 2006, 6:57:15 AM10/3/06
to RubyOnRails to russian
А кто мешает в условии написать
&& pfile.original_filename =~ /\.jpg$/

Serhiy Boiko

unread,
Oct 3, 2006, 7:55:04 AM10/3/06
to ror...@googlegroups.com
On Tuesday 03 October 2006 13:18, Denis Surkov wrote:
> Как можно реализовать сабж? Пока использую такое:
>

Вобщем-то аплоад файлов одна из самых гимморойных задач под веб. И что под пхп
что под рейлс приходится мудохаться чтобы сделать это универсально и один
раз.

Есть много подводных камней. Например, чтобы тебе не залили пхп-ешный файл и
не хакнули сервер. Или чтобы новая картинка не затерла старую. Кроме того,
если используешь картинки, часто нужно их ресайзить. При этом если это гифка
иногда ее приходится приводить к jpg-у или png чтобы вид был симпатичный.
Опять же, отресайзенную картинку нужно правильно обозвать что-то типа
image-small.gif и т.п.

Кроме того, в админке желательно делать превью в форме админки, чтобы было
видно, что ты залил. Но будет некрасиво если эта картинка будет большая и
разнесет тебе форму на весь экран - и нужно делать ресайз джаваскриптом.

И на добавку кинем флеш. Это вообще отдельная песня, уже для того, чтобы
сделать его вывод, нужно знать его размеры, а как ты узнаешь размеры
флеш-картинки, если сам же их и не задашь.

Ну что, испугался? :))

Вот две ссылки:
Acts as Attachment in Plugins:
http://technoweenie.stikipad.com/plugins/show/Acts+as+Attachment
file_column plugin: http://www.kanthak.net/opensource/file_column/

Звезд с неба не ловят, но позволяют не морочиться с проверками расширений и
самим аплоадом файла.

--
Serhiy Boiko
CRIS-UANIC

Julian 'Julik' Tarkhanov

unread,
Oct 3, 2006, 8:23:28 AM10/3/06
to ror...@googlegroups.com

On 3-okt-2006, at 13:55, Serhiy Boiko wrote:

> Есть много подводных камней.
> Например, чтобы тебе не залили пхп-
> ешный файл и
> не хакнули сервер. Или чтобы новая
> картинка не затерла старую. Кроме
> того,
> если используешь картинки, часто
> нужно их ресайзить. При этом если это
> гифка
> иногда ее приходится приводить к jpg-у
> или png чтобы вид был симпатичный.
> Опять же, отресайзенную картинку
> нужно правильно обозвать что-то типа
> image-small.gif и т.п.

и все все все это (и даже больше) делает
file_column
>
> Кроме того, в админке желательно
> делать превью в форме админки, чтобы
> было
> видно, что ты залил. Но будет
> некрасиво если эта картинка будет
> большая и
> разнесет тебе форму на весь экран - и
> нужно делать ресайз джаваскриптом.
>
> И на добавку кинем флеш. Это вообще
> отдельная песня, уже для того, чтобы
> сделать его вывод, нужно знать его
> размеры, а как ты узнаешь размеры
> флеш-картинки, если сам же их и не
> задашь.
решение простое как огурец - при
загрузке для флешек указывается имя
типа

myMovie_320x240.swf

и это открытым текстом заявляется в
интерфейсе

--
Julian 'Julik' Tarkhanov
please send all personal mail to
me at julik.nl


Serhiy Boiko

unread,
Oct 3, 2006, 8:40:46 AM10/3/06
to ror...@googlegroups.com
> решение простое как огурец - при
> загрузке для флешек указывается имя
> типа
>
> myMovie_320x240.swf

А за это спасибо, действительно хорошая идея :).

--
Serhiy Boiko
CRIS-UANIC

Yaroslav Markin

unread,
Oct 3, 2006, 10:02:05 AM10/3/06
to ror...@googlegroups.com
Чтобы не изобретать велосипед, смотри на acts_as_attachment

# acts_as_attachment :content_type => 'application/pdf'
# acts_as_attachment :content_type => ['application/pdf',
'application/msword', 'text/plain']
# acts_as_attachment :content_type => :image, :resize_to =>
[50,50]

http://svn.techno-weenie.net/projects/plugins/acts_as_attachment/

http://technoweenie.stikipad.com/plugins/show/Acts+as+Attachment

On 03.10.2006, at 14:18, Denis Surkov wrote:

> Как можно реализовать сабж? Пока использую такое:


--
Yaroslav Markin
yaroslav at markin dot net
http://www.evilmartians.com/
http://www.rubyonrails.ru/

Timur Vafin

unread,
Oct 3, 2006, 10:35:10 AM10/3/06
to Yaroslav Markin
Здравствуйте, Yaroslav.

Вы писали 3 октября 2006 г., 18:02:05:

> Чтобы не изобретать велосипед, смотри на acts_as_attachment

А вот расскажите как сделать при помощи этого плагина более одной
картинки?


--
С уважением,
Timur mailto:tim...@gmail.com

Yaroslav Markin

unread,
Oct 3, 2006, 10:41:17 AM10/3/06
to ror...@googlegroups.com
On 03.10.2006, at 18:35, Timur Vafin wrote:

> А вот расскажите как сделать при помощи этого плагина более одной
> картинки?
>

Item
has_many :pictures

Picture
belongs_to :item
acts_as_attachment

или ты что-то другое имел в виду?

Yaroslav Markin

unread,
Oct 3, 2006, 10:42:39 AM10/3/06
to ror...@googlegroups.com

On 03.10.2006, at 18:35, Timur Vafin wrote:
>> Чтобы не изобретать велосипед, смотри на acts_as_attachment
>
> А вот расскажите как сделать при помощи этого плагина более одной
> картинки?
>

Или ты про изменение размеров картинок? Там все это есть, нормальная
работа с rmagick, для каждого acts_as_attachment делается несколько
thumbs, у каждого parent_id указывает на родительский элемент

Timur Vafin

unread,
Oct 3, 2006, 11:16:17 AM10/3/06
to Yaroslav Markin
Здравствуйте, Yaroslav.

Вы писали 3 октября 2006 г., 18:41:17:

> On 03.10.2006, at 18:35, Timur Vafin wrote:

>> А вот расскажите как сделать при помощи этого плагина более одной
>> картинки?

> Item
> has_many :pictures

> Picture
> belongs_to :item
> acts_as_attachment

> или ты что-то другое имел в виду?

Ну как то мне кажется это намного сложнее, чем просто
описать у модели, что у нее есть большая картинка и маленькая
картинка, что позволяет делать file_column.

Yaroslav Markin

unread,
Oct 3, 2006, 11:23:52 AM10/3/06
to ror...@googlegroups.com
>>> А вот расскажите как сделать при помощи этого плагина более одной
>>> картинки?
>
>> Item
>> has_many :pictures
>
>> Picture
>> belongs_to :item
>> acts_as_attachment
>
>> или ты что-то другое имел в виду?
>
> Ну как то мне кажется это намного сложнее, чем просто
> описать у модели, что у нее есть большая картинка и маленькая
> картинка, что позволяет делать file_column.

Давай будем писать вопросы покорректнее :)

acts_as_attachment :content_type => :image, :resize_to => [50,50]

acts_as_attachment :thumbnails => { :thumb => [50, 50], :geometry =>
'x50' }

То что ты можешь сделать в file_column, ты можешь сделать и здесь.
Лично я больше fc не пользуюсь.

Dmytro Shteflyuk

unread,
Oct 3, 2006, 11:29:30 AM10/3/06
to ror...@googlegroups.com
2006/10/3, Yaroslav Markin <yaro...@markin.net>:

> Давай будем писать вопросы покорректнее :)
>
> acts_as_attachment :content_type => :image, :resize_to => [50,50]
> acts_as_attachment :thumbnails => { :thumb => [50, 50], :geometry =>
> 'x50' }

Вот именно, покорректнее
Большая и маленькая картинки абсолютно разные.
Например, большая - это фотография меня в полный рост, а маленькая -
морда забавной собачки. Как такое сделать?
--
Best regards, Dmytro Shteflyuk

Timur Vafin

unread,
Oct 3, 2006, 11:35:06 AM10/3/06
to Yaroslav Markin
Здравствуйте, Yaroslav.

Вы писали 3 октября 2006 г., 19:23:52:

>>>> А вот расскажите как сделать при помощи этого плагина более одной
>>>> картинки?
>>
>>> Item
>>> has_many :pictures
>>
>>> Picture
>>> belongs_to :item
>>> acts_as_attachment
>>
>>> или ты что-то другое имел в виду?
>>
>> Ну как то мне кажется это намного сложнее, чем просто
>> описать у модели, что у нее есть большая картинка и маленькая
>> картинка, что позволяет делать file_column.

> Давай будем писать вопросы покорректнее :)

> acts_as_attachment :content_type => :image, :resize_to => [50,50]
> acts_as_attachment :thumbnails => { :thumb => [50, 50], :geometry =>
> 'x50' }

Что то видимо я не до конца разобрался.

У меня было представление что к модели можно привязать только одно
изображение.

Если конкретизировать, то как сделать чтобы у модели были 2 разные
картинки =)

Yaroslav Markin

unread,
Oct 3, 2006, 11:39:52 AM10/3/06
to ror...@googlegroups.com
On 03.10.2006, at 19:35, Timur Vafin wrote:

> Что то видимо я не до конца разобрался.
>
> У меня было представление что к модели можно привязать только одно
> изображение.
>
> Если конкретизировать, то как сделать чтобы у модели были 2 разные
> картинки =)
>

Смотри, если нужно чтобы было просто две разные картинки -- то это
has_many отношение: у модели есть много картинок.

Если тебе надо делать уменьшенные копии картинок, например
(thumbnails) -- то такая возможность зашита и в file_column, и в
acts_as_attachment. В AAA можно вешаться на after_resize,
after_attachment_saved, before_thumbnail_saved и всякое такое.

Yaroslav Markin

unread,
Oct 3, 2006, 11:40:31 AM10/3/06
to ror...@googlegroups.com

Тогда это по смыслу две разные картинки -- две разные модели которые
относятся к родительской.

Yaroslav Markin

unread,
Oct 3, 2006, 11:47:03 AM10/3/06
to ror...@googlegroups.com
On 03.10.2006, at 19:29, Dmytro Shteflyuk wrote:

> Вот именно, покорректнее
> Большая и маленькая картинки абсолютно разные.
> Например, большая - это фотография меня в полный рост, а маленькая -
> морда забавной собачки. Как такое сделать?

Да, и если ни thumbnails, ни has_many не подходят, то, как и всегда,
есть два универсальных варианта

1. Сделать таблицу attachments и Attachment, и наследовать его как
single table inheritance
2. Использовать polymorphic associations на эту таблицу

Timur Vafin

unread,
Oct 3, 2006, 11:47:59 AM10/3/06
to Yaroslav Markin
Здравствуйте, Yaroslav.

Вы писали 3 октября 2006 г., 19:40:31:

> On 03.10.2006, at 19:29, Dmytro Shteflyuk wrote:

>> 2006/10/3, Yaroslav Markin <yaro...@markin.net>:
>>> Давай будем писать вопросы покорректнее :)
>>>
>>> acts_as_attachment :content_type => :image, :resize_to => [50,50]
>>> acts_as_attachment :thumbnails => { :thumb => [50, 50], :geometry =>
>>> 'x50' }
>>
>> Вот именно, покорректнее
>> Большая и маленькая картинки абсолютно разные.
>> Например, большая - это фотография меня в полный рост, а маленькая -
>> морда забавной собачки. Как такое сделать?

> Тогда это по смыслу две разные картинки -- две разные модели которые
> относятся к родительской.

Тогда ясно, я сталкивался с тем что у моделей просто бывает несколько
изображений различных.

Думаю в случае file_column это сделать много проще =)

Maks

unread,
Oct 3, 2006, 12:47:16 PM10/3/06
to RubyOnRails to russian
Вообщем то file_column замечательная штука,
но может еще имеет смысл сделать все
самому.
Попробую привести пример "решения для
картинок", и разобравшись с кодом можно
легко переделать (усложнить/упрастить)
под свою задачу:

Тут примерно такая задача:
1. Сохранять любые файлы с картинками
только в предопределенном расширении.
2. Сохранять сразу несколько версий
размеров.

#controller
class ImagesController < ApplicationController
...
def create_me
if Photo.exists?(params[:photo_id].to_i)
@photo = Photo.find(params[:photo_id].to_i)
@photo.file = @params[:testfile][:file]
else
@photo = Photo.new(@params[:testfile])
end

redirect_to :action => 'new_image'
end
...
end
redirect_to :action => 'new_image'
end

#model
require 'RMagick'
require 'digest/md5'

class Photo < ActiveRecord::Base
STORE_DIR = "#{RAILS_ROOT}/public/photos"
MAIN_EXT = 'png'
@@versions = {:MAIN => '320x240', :thumb => '100x100'}

before_destroy :before_destroy
...
def file=(uploaded_file)
@uploaded_file = uploaded_file
if self.new_record?
@filename = "#{general_name}.#{MAIN_EXT}"
else
@filename = self.photo
end
self.photo = @filename
end

def after_save
if !File.exists?(File.dirname(path_to_file))
Dir.mkdir(File.dirname(path_to_file))
end
if @uploaded_file.instance_of?(Tempfile)
FileUtils.copy(@uploaded_file.local_path, path_to_file)
else
File.open(self.path_to_file, "wb") { |f|
f.write(@uploaded_file.read) }
end
saved_file = ::Magick::Image.read(self.path_to_file).first
@@versions.each{|key,value|
saved_file.clone.change_geometry!(value) { |cols, rows, img|
img.resize!(cols, rows)
file_name = self.photo.split('.').first
if key.to_s =~ /MAIN/i
img.write File.join(STORE_DIR,"#{file_name}_.#{MAIN_EXT}")
else
img.write
File.join(STORE_DIR,"#{file_name}_#{key.to_s}.#{MAIN_EXT}")
end
}
}
if File.exists?(path_to_file)
File.delete(path_to_file)
end
end
...
end

Все это взято/переделано/упращено из
из того же file_column.
Если заинтересует, то могу помочь, если
что то непонятно, или же переслать
рабочий проект.

Yaroslav Markin

unread,
Oct 3, 2006, 12:57:54 PM10/3/06
to ror...@googlegroups.com
On 03.10.2006, at 19:47, Timur Vafin wrote:

>> Тогда это по смыслу две разные картинки -- две разные модели которые
>> относятся к родительской.
>
> Тогда ясно, я сталкивался с тем что у моделей просто бывает несколько
> изображений различных.
>
> Думаю в случае file_column это сделать много проще =)

В file_column изображение -- это просто ссылка на файл, а в AAA это
все-таки модель. Когда как удобнее..

Maxim Kulkin

unread,
Oct 4, 2006, 4:27:11 AM10/4/06
to ror...@googlegroups.com
On 3 October 2006 20:57, Yaroslav Markin wrote:
> On 03.10.2006, at 19:47, Timur Vafin wrote:
> >> Тогда это по смыслу две разные картинки -- две разные модели которые
> >> относятся к родительской.
> >
> > Тогда ясно, я сталкивался с тем что у моделей просто бывает несколько
> > изображений различных.
> >
> > Думаю в случае file_column это сделать много проще =)
>
> В file_column изображение -- это просто ссылка на файл, а в AAA это
> все-таки модель. Когда как удобнее..
Я в свое время пытался заставить file_column все файлы для одного экземпляра
хранить в одной папке (в случае с картинками надо было срезайзить к
определенному размеру и выбрать правильное расширение на основе типа MIME).
Так вот мне это так и не удалось. Там схема с папками настолько вплетена
внутрь file_column, что сменить ее очень сложно. Пришлось написать руками.

Делать там на самом деле не много. Так что если надо захранить две картинки
для одного экземпляра, например, пользователя, не надо перекраивать и
выделять их в новую сущность. Такая нормализация сама по себе, конечно,
хорошая вещь, но она может понизить производительность.

Julian 'Julik' Tarkhanov

unread,
Oct 4, 2006, 5:42:13 AM10/4/06
to ror...@googlegroups.com

On 4-okt-2006, at 10:27, Maxim Kulkin wrote:

> Там схема с папками настолько
> вплетена
> внутрь file_column, что сменить ее очень
> сложно. Пришлось написать руками.
Не надо плыть против потока. Схема (на
основе идентификатора обьекта к
которому привязан аттачмент) сделана
таким образом
чтобы предотвратить переполнение
директирии (большинство опенсорсных
файловых систем начинают очень круто
кашлять при превышении определенного
количества записей в директории).

Maxim Kulkin

unread,
Oct 4, 2006, 6:10:26 AM10/4/06
to ror...@googlegroups.com
On 4 October 2006 13:42, Julian 'Julik' Tarkhanov wrote:
> On 4-okt-2006, at 10:27, Maxim Kulkin wrote:
> > Там схема с папками настолько
> > вплетена
> > внутрь file_column, что сменить ее очень
> > сложно. Пришлось написать руками.
> Не надо плыть против потока.
Где-то я это уже слышал.
У Вас неправильное понимание "потока".

К тому же, поток - потоком, а валидации таки отделились от моделей (см.
ActiveSpec)

> Схема (на основе идентификатора обьекта к
> которому привязан аттачмент) сделана
> таким образом
> чтобы предотвратить переполнение
> директирии (большинство опенсорсных
> файловых систем начинают очень круто
> кашлять при превышении определенного
> количества записей в директории).

Меня волновал не ID, а то, что он привязывается к classname/attributename/.
Мне надо было, чтобы все (немногочисленные) файлики одного экземпляра модели
лежали в, к примеру, mymodel/id/ и назывались myattribute<n>.<correct
extension>

А в file_column один аттрибут - это отдельная папочка, где он складывает
подпапки, соответствующие id объектов. Похоже по дефолты сделаны routes:
:controller/:action/:id
вместо
:controller/:id/:action

В случае последних тут все понятно - есть экшены, которым не нужен id. А вот с
file_column - имхо, большой минус.

Sergey Kojin

unread,
Oct 4, 2006, 7:07:32 AM10/4/06
to RubyOnRails to russian
> К тому же, поток - потоком, а валидации таки отделились от моделей (см.
> ActiveSpec)

Ну как же отделились, как я понял ActiveSpec
это сторонний проект, просто автор
заюзал префикс Active

Maxim Kulkin

unread,
Oct 4, 2006, 7:36:22 AM10/4/06
to ror...@googlegroups.com
Да это понятно. И я могу предположить, что они еще долго не станут частью
Rails и будут использоваться только в качестве плагина.

Но теперь это "научно обоснованный" =) подход.

Спецификации при определенном использовании идентичны существующим в Rails
валидациям , но, имхо, сами по себе более удобные.

Yaroslav Markin

unread,
Oct 4, 2006, 8:45:30 AM10/4/06
to ror...@googlegroups.com
On 04.10.2006, at 14:10, Maxim Kulkin wrote:

>> Схема (на основе идентификатора обьекта к
>> которому привязан аттачмент) сделана
>> таким образом
>> чтобы предотвратить переполнение
>> директирии (большинство опенсорсных
>> файловых систем начинают очень круто
>> кашлять при превышении определенного
>> количества записей в директории).
> Меня волновал не ID, а то, что он привязывается к classname/
> attributename/.
> Мне надо было, чтобы все (немногочисленные) файлики одного
> экземпляра модели
> лежали в, к примеру, mymodel/id/ и назывались myattribute<n>.<correct
> extension>
>

Используйте AAA или перепишите file_column, он небольшой.
Reply all
Reply to author
Forward
0 new messages