[Rails] SWF upload 사용하기
swf upload
SWFUpload 는 flash/javascript를 이용해서 file upload를 쉽게 구현할 수 있도록 해 준다.
다음과 같은 장점을 갖는다.
- 여러개의 파일을 선택하고 업로드 할 수 있다.
- 파일을 선택하면서 file type에 대한 검사를 할 수 있다.
- 파일을 선택하면서 file 크기에 대한 검사를 할 수 있다.
- 파일 업로드 상태(프로그레스)를 구현하기 쉽다.
- javascript/flash가 사용불가능한 경우에는 기존의 방법(HTML)을 사용할 수 있다.(Degrades gracefully)
다운로드를 받아서 내용을 풀어보면, 잘 정리된 문서와 풍부한 예제 코드들을 볼 수 있다. 비록 php로 작성되어 있지만, 기능을 살펴보는 데 있어서는 부족함이 없을 것이다.
rails에서 swf upload사용하기
문서화가 잘 되어 있어서 사용하기는 많이 어렵지 않을 것이다.
내가 필요했던 API들을 간단히 정리한 문서가 여기 있다.
flash가 가지고 있는 cookie 버그를 해결한 문서 도 도움이 될 것이다.
업로드를 사용하는 요청에 respond_to 문법을 사용하면 제대로 동작하지 않을 수도 있는데, 그것은 SWFUpload 의 업로드 요청이
- HTTP_ACCEPT = "text/*"
이기 때문이다. 가장 간단한 해결책은 mime_type.rb에 다음을 추가하는 것일 듯 싶다.(이상하지만..)
- Mime::Type.register "text/*", :flash
그러면 response_to 에서 다음과 같이 사용할 수 있다.
- format.flash { render :text => @sbox.id.to_s, :layout=>false }
참조
swf upload를 사용해서 file upload하기
SWFUpload API 요약 정리
SWFUpload 의 method들
SWFUpload의 Documentation 의 내용을 정리/요약한 것이다. (version 2.1.0 기준)
더 자세한 내용은 위 사이트를 통해 확인할 것.
selectFile(), seletFiles()
파일을 선택하는 파일 선택 창을 보여준다.
selectFile은 한개만 선택할 수 있고, selectFiles는 여러 파일을 선택할 수 있다.
startUpload(file_id)
file_id의 파일 업로드 수행한다.
file_id가 없으면 큐의 첫번째 파일의 업로드를 수행한다.
cancelUpload(file_id)
대기중인 파일 혹은 업로드 중인 파일을 취소한다.
업로드 중이었다면 uploadError 발생힌다.
file_id가 없으면 큐의 첫 번째 파일을 취소한다.
stopUpload(file_id)
업로드 중인 파일 취소 후 다시 큐에 넣는다.
uploadError 발생한다.
addPostParam(name, value)
파일 업르드 시 POST 요청에 보낼 파라미터를 추가한다.
setPostParams(param_object)
POST 요청에 보낼 파라미터를 입력된 파라미터로 변경한다.
param_object 는 {name:value} 쌍을 갖는 javascript object이다.
removePostParam(name)
POST 요청에 보낼 파라미터를 삭제한다.
addFileParam(file_id, name, value)
파일 업로드 시 POST 요청에 보낼 파라미터를 추가한다.
addPostParam과 다른 점은 addPostParam은 업로드를 수행하는 모든 파일들에 적용되는 글로벌 설정인데 비해, addFileParam은 각각의 업로드 하는 파일 별로 설정이 된다는 점이다.
removeFileParam(fild_id, name)
파라미터를 제거한다.
destory
swfu 객체 및 DOM을 제거한다.
event handler들
다음 event handler들은 SWFUpload를 초기화하면서 init_settings 를 통해 override할 수 있다.
swfUploadLoaded()
플래시가 로드된 직후 불려진다. degraded_form을 사용하는 경우에 여기에서 변경할 수 있다.
fileDialogStart()
selectFile(), selectFiles() 가 호출되면 파일 선택 창이 뜨는데, 이 때 불려진다.
fileQueued(fileObj)
선택한 파일이 큐에 들어가면서 불려진다.
fileQueueError(file object, error code, message)
파일을 큐에 넣는 것을 실패했을 때 불려진다.
에러코드의 내용은 SWFUpload.QUEUE_ERROR 를 참조.
fileDialogComplete(number of files selected)
파일 선택과 선택한 파일을 큐에 넣는 동작을 모두 마친 후 불려진다.
선택하자마자 업로드를 진행하고 싶다면 여기에서 startUpload()를 호출하면 된다.
uploadStart(file object)
파일 업로드가 수행되기 직전에 불려진다.
여기서 false를 return하면 업로드를 진행하지 않는다.
파일 validation 혹은 POST 파라미터를 추가하기 좋은 위치이다.
uploadProgress(file object, bytes complete, total bytes)
파일의 업로드 중에 주기적으로 플래시에 의해 불려진다.
파일 업로드 진행 상황을 확인할 수 있다. 업로드 프로그레스를 구현하기에 좋은 위치이다.
uploadError(file object, error code, message)
업로드 중 에러가 발생하면 불려진다.
error code는 SWFUpload.UPLOAD_ERROR 에서 확인할 수 있다.
uploadSuccess(file object, server data)
업로드가 성공했을 때 불려진다.
server data는 성공시에 HTTP Response 에 담겨진 내용임.(플래시 9에서만 동작함)
uploadComplete(file object)
업로드의 성공, 실패에 상관없이 마지막에 불려진다.
다음 큐의 업로드를 자동으로 수행하고 싶으면 여기에서 startUpload()를 호출하면 된다.
debug(message)
디버그 이벤트시 불려진다.
settigns
upload_url
업로드를 수행할 URL
file_post_name
업로드를 수행할 때 선택한 파일을 POST 파라미터에 넣어서 보낼텐데, 이때 그 파일을 가르키는 파라미터의 이름. 기본값은 "Filedata"
post_params
추가적으로 POST 파라미터에 전해질 내용들. 모든 파일의 업로드시에 적용된다.
use_query_string
설정한 POST 파라미터를 query_string(URL의 ? 뒷부분)에 넣어서 보낼 것인지를 결정.
query_string에 넣어서 보내면 무슨 장점이 있지..?
file_types
선택 가능한 파일 확장자들
예) *.doc;*.hwp
file_types_description
파일 타입에 대한 설명
file_size_limit
업로드할 파일 하나의 최대 크기
file_upload_limit
업로드 가능한 최대 파일의 수. 0은 무한대
file_queue_limit
큐에 들어갈 수 있는 최대 파일의 수. 0은 무한대
flash_url
flash의 URL, 왠만하면 V9를 사용하자.
custom_settings
개발자가 자기만의 정보를 swfu안에 넣고, 꺼내고 할 수 있도록 만들어준 창고같은 녀석.
[rails]SWFUpload 사용할 때 Cookie 버그
SWF upload 플래시는 cookie의 값을 서버로 제대로 전송해 주지 못한다. 무슨 내용인지 궁금하면 다음을 읽어보라.
http://swfupload.org/forum/generaldiscussion/383
IE가 아닌 다른 브라우저에서는 IE의 쿠키값을 보낸다는 듯 하다.
이유야 어찌됬든 파일 업로드는 사용자가 로그인한 상태에서 행해지는 것이 대부분일테고, 그리고 사용자의 로그인을 restful authentication의 login_required 같은 before_filter에 의해 보장받고 싶다면, SWFUpload를 이용한 업로드는 문제가 있다.
세션 정보가 제대로 전해지지 않기에 login_required는 실패를 할 테고, 업로드 액션에 도달하지도 못하고 끝이 날 것이다.
이를 해결하는 방법 중 하나는 session 정보를 업로드 요청의 파라미터로 보내서 그것으로부터 session 정보를 복구해내는 것이다.Upload files with SWFUpload 를 보면 session 정보를 URI의 query_string에 전하고, class CGI::Session 과 class CGI::Session::CookieStore 를 해킹해서 해결했다. 이 방법은 잘 동작한다. 이렇게 해도 별 무리가 없을 듯하지만...
어떤 이유 (- 모든 요청에 대해 query_string을 조사하는 것이 꺼림직하다. -) 에서든지 session 정보를 query_string이 아닌 POST 파라미터로 보내고 싶다면 다음과 같은 방법을 사용할 수도 있다.
여기서는 sesion 정보를 POST 파라미터로 전하고 action의 before_filter를 이용해서 session 정보를 복구하도록 하는 방법을 소개한다.
1. flash의 upload 요청에 session 값을 POST 파라미터로 전해준다.
다음과 같이 swfupload가 post_parameter 에 session_id를 전해주도록 한다.
- new SWFUpload({
- post_params: {"_app_session_id" : <%= session.session_id %>},
-
...
% Rails 2.1에서는 session_id 에 '\n' 이 포함되어 있다. 왜 그런거지..? 그래서 javascript 에러가 발생한다. session.session_id.gsub("\n", "\\n") 이렇게 해주니까 잘 되더라.(이.. 깊이없는 땜빵....음냐..)
2. before_filter를 이용해서 파라미터에서 session 정보를 얻도록 한다.
SWFUpload 를 이용해서 업로드를 수행하고자 하는 action을 retrieve_session_from_param 로 보호하도록 한다. retrieve_session_from_param은 params로 부터 session을 복구할 것이다. 주의할 것은 retrieve_session_from_param 가 login_require 보다 먼저 실행되어야 한다.
- class PhotosController < ApplicationController
- before_filter :retrieve_session_from_param, :only=>[:create]
- before_filter :login_required
2.1. retrieve_session_from_param
parameter로 부터 session 정보를 얻어오는 함수 retrieve_session_from_param을 app/controllers/application.rb에 추가한다.
- def retrieve_session_from_param
session_key = ActionController::Base.session[0][:session_key]
return if params[session_key].blank?
self.session = CGI::Session.new(request,
'database_manager' => CGI::Session.const_get((:cookie_store).to_s.camelize),
'new_session' => false,
'session_key' => session_key,
'secret' => ActionController::Base.session[0][:secret],
'session_data' => params[session_key],
'session_id' => params[session_key] )
end
code 설명
sesson_key 가 params에 있으면 params[:session_key]로부터 session을 만들도록 하자. session_key는 environment에서 config.action_controller.session 에 적어준 그 값이다.
params[:session_key] 있다면 그로부터 session을 생성해서 controller의 session값과 바꿔치기하자. 이 때 database_manager는 CookieStore를 이용한다. 그리고 session_data라는 파라미터도 전해주는데, 이 값은 CookieStore 인스턴스를 만들때 그대로 전해질 것이다.
2.2. CGI::Session::CookieStore 의 해킹
CGI::Session::CookieStore가 session 정보를 session_data 에서 우선적으로 읽어올 수 있도록 하자.
config/initializers/swf_upload.rb를 만들어 다음 내용을 추가한다.(좋지 않아 보인다..)
- class CGI::Session::CookieStore
alias original_initialize initialize - alias original_read_cookie read_cookie
def initialize(session, options = {})
@session_data = options['session_data']
original_initialize(session, options)
end
def read_cookie
@session_data || original_read_cookie
end
end
code의 설명
options['session_data'] 를 파라미터로 받으면 이 값을 @session_data 에 저장하고 있다가 read_cookie 시에 return하도록 한다. 그러면 session을 cookie에서가 아닌 입력받은 파라미터(options['session_data'])에서 얻을 수 있다.
출처 : http://aproxacs.springnote.com/pages/390446
페이지 히스토리
2009-09-18 14:44 에 ALICE님이 마지막으로 수정
엮인페이지
'프로그래밍 > 기타' 카테고리의 다른 글
SVN X remains in tree-conflict (1) | 2012.03.22 |
---|---|
ER Win 7.3에서 MySQL 연결하기 (0) | 2010.10.07 |
바코드구조 (0) | 2010.06.07 |
QR코드 자동생성 유틸 (0) | 2010.04.26 |
폴더플러스 한글자 검색 제한 패치 강좌 (0) | 2010.04.23 |