with rails active ruby-on-rails flex file-upload paperclip

ruby on rails - active - Excepción al intentar cargar un archivo de Flex a Rails(con clip)



rails gem upload file (1)

Intento subir un archivo generado dinámicamente desde Flex (imagen PNG) a la parte posterior del Servidor Ruby on Rails utilizando el siguiente código (del libro Flex on Rails):

public function save():void { var bitmapData:BitmapData = new BitmapData(width, height); bitmapData.draw(this); var ba:ByteArray = (new PNGEncoder()).encode(bitmapData); var fileRef:FileReference = new FileReference(); //TODO: Remove HardCoding of URL here var request : URLRequest = new URLRequest("http://localhost:3000/doodles"); request.method = URLRequestMethod.POST; var boundary : String = "----------Ij5GI3GI3ei4GI3ei4KM7GI3KM7KM7"; request.contentType = "multipart/form-data; boundary=" + boundary; request.data =getMultiPartRequestData(boundary,''doodle'','''',ba); loader.load(request); }

y la función getMultiPartRequestData es:

private function getMultiPartRequestData(boundary:String, resourceName:String, filename:String, bytes:ByteArray):ByteArray { Alert.show("haha"); var lf:String = "/r/n"; var part1:String = ''--'' + boundary + lf + ''Content-Disposition: form-data; name="Filename"'' + lf + lf + ''{0}'' + lf + ''--'' + boundary + lf ; if (_model.authenticityToken != "") { part1 += ''Content-Disposition: form-data; name="authenticity_token";'' + lf + lf + ''{2}'' + lf + ''--'' + boundary + lf ; } part1 += ''Content-Disposition: form-data; name="{1}[x]";'' + lf + lf + ''{3}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[y]";'' + lf + lf + ''{4}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[width]";'' + lf + lf + ''{5}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[height]"'' + lf + lf + ''{6}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[rotation]"'' + lf + lf + ''{7}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[day_id]"'' + lf + lf + ''{8}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[privacy]"'' + lf + lf + ''{9}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[canvas_height]"'' + lf + lf + ''{10}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[canvas_width]"'' + lf + lf + ''{11}'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="commit"'' + lf + lf + ''Create'' + lf + ''--'' + boundary + lf + ''Content-Disposition: form-data; name="{1}[photo]";'' + ''filename="{0}"'' + lf + ''Content-Type: application/octet-stream'' + lf + lf var part2:String = ''--'' + boundary + lf + ''Content-Disposition: form-data; name="Upload"'' + lf + lf + ''Submit Query'' + lf + ''--'' + boundary + ''--'' var result:ByteArray = new ByteArray(); // Filling in the parameters as per comment above result.writeMultiByte(StringUtil.substitute(part1, filename, resourceName, _model.authenticityToken, _model.boundMinX, _model.boundMinY, Constants.DEFAULT_DOODLE_WIDTH, Constants.MINIMUM_CANVAS_HEIGHT, 0, _model.current_day.id, privacyGroup.selectedValue.toString(), FlexGlobals.topLevelApplication.height, FlexGlobals.topLevelApplication.width), "ascii"); result.writeBytes(bytes,0,bytes.length); result.writeMultiByte(part2, "ascii"); return result; }

Obtengo la siguiente excepción:

TypeError (can''t convert nil into String): vendor/plugins/paperclip/lib/paperclip/iostream.rb:8:in `extname'' vendor/plugins/paperclip/lib/paperclip/iostream.rb:8:in `to_tempfile'' vendor/plugins/paperclip/lib/paperclip/attachment.rb:89:in `assign'' vendor/plugins/paperclip/lib/paperclip.rb:262:in `block in has_attached_file'' activerecord (2.3.5) lib/active_record/base.rb:2746:in `block in attributes='' activerecord (2.3.5) lib/active_record/base.rb:2742:in `each'' activerecord (2.3.5) lib/active_record/base.rb:2742:in `attributes='' activerecord (2.3.5) lib/active_record/base.rb:2438:in `initialize'' app/controllers/doodles_controller.rb:16:in `new'' app/controllers/doodles_controller.rb:16:in `create'' actionpack (2.3.5) lib/action_controller/base.rb:1331:in `perform_action'' actionpack (2.3.5) lib/action_controller/filters.rb:617:in `call_filters'' actionpack (2.3.5) lib/action_controller/filters.rb:610:in `perform_action_with_filters'' actionpack (2.3.5) lib/action_controller/benchmarking.rb:68:in `block in perform_action_with_benchmark'' activesupport (2.3.5) lib/active_support/core_ext/benchmark.rb:17:in `block in ms'' /Users/tammam56/.rvm/rubies/ruby-1.9.1-p378/lib/ruby/1.9.1/benchmark.rb:309:in `realtime'' activesupport (2.3.5) lib/active_support/core_ext/benchmark.rb:17:in `ms'' actionpack (2.3.5) lib/action_controller/benchmarking.rb:68:in `perform_action_with_benchmark'' actionpack (2.3.5) lib/action_controller/rescue.rb:160:in `perform_action_with_rescue'' actionpack (2.3.5) lib/action_controller/flash.rb:146:in `perform_action_with_flash'' vendor/plugins/newrelic_rpm/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:253:in `block in perform_action_with_newrelic_trace'' vendor/plugins/newrelic_rpm/lib/new_relic/agent/method_tracer.rb:141:in `trace_execution_scoped'' vendor/plugins/newrelic_rpm/lib/new_relic/agent/instrumentation/controller_instrumentation.rb:246:in `perform_action_with_newrelic_trace'' actionpack (2.3.5) lib/action_controller/base.rb:532:in `process'' actionpack (2.3.5) lib/action_controller/filters.rb:606:in `process_with_filters'' actionpack (2.3.5) lib/action_controller/base.rb:391:in `process'' actionpack (2.3.5) lib/action_controller/base.rb:386:in `call'' actionpack (2.3.5) lib/action_controller/routing/route_set.rb:437:in `call'' actionpack (2.3.5) lib/action_controller/dispatcher.rb:87:in `dispatch'' actionpack (2.3.5) lib/action_controller/dispatcher.rb:121:in `_call'' actionpack (2.3.5) lib/action_controller/dispatcher.rb:130:in `block in build_middleware_stack'' activerecord (2.3.5) lib/active_record/query_cache.rb:29:in `call'' activerecord (2.3.5) lib/active_record/query_cache.rb:29:in `block in call'' activerecord (2.3.5) lib/active_record/connection_adapters/abstract/query_cache.rb:34:in `cache'' activerecord (2.3.5) lib/active_record/query_cache.rb:9:in `cache'' activerecord (2.3.5) lib/active_record/query_cache.rb:28:in `call'' activerecord (2.3.5) lib/active_record/connection_adapters/abstract/connection_pool.rb:361:in `call'' actionpack (2.3.5) lib/action_controller/string_coercion.rb:25:in `call'' rack (1.0.1) lib/rack/head.rb:9:in `call'' rack (1.0.1) lib/rack/methodoverride.rb:24:in `call'' actionpack (2.3.5) lib/action_controller/params_parser.rb:15:in `call'' actionpack (2.3.5) lib/action_controller/session/cookie_store.rb:93:in `call'' actionpack (2.3.5) lib/action_controller/failsafe.rb:26:in `call'' rack (1.0.1) lib/rack/lock.rb:11:in `block in call'' <internal:prelude>:8:in `synchronize'' rack (1.0.1) lib/rack/lock.rb:11:in `call'' actionpack (2.3.5) lib/action_controller/dispatcher.rb:114:in `block in call'' actionpack (2.3.5) lib/action_controller/reloader.rb:34:in `run'' actionpack (2.3.5) lib/action_controller/dispatcher.rb:108:in `call'' rails (2.3.5) lib/rails/rack/static.rb:31:in `call'' rack (1.0.1) lib/rack/urlmap.rb:46:in `block in call'' rack (1.0.1) lib/rack/urlmap.rb:40:in `each'' rack (1.0.1) lib/rack/urlmap.rb:40:in `call'' rails (2.3.5) lib/rails/rack/log_tailer.rb:17:in `call'' rack (1.0.1) lib/rack/content_length.rb:13:in `call'' rack (1.0.1) lib/rack/chunked.rb:15:in `call'' rack (1.0.1) lib/rack/handler/mongrel.rb:64:in `process'' mongrel (1.1.5) lib/mongrel.rb:159:in `block in process_client'' mongrel (1.1.5) lib/mongrel.rb:158:in `each'' mongrel (1.1.5) lib/mongrel.rb:158:in `process_client'' mongrel (1.1.5) lib/mongrel.rb:285:in `block (2 levels) in run''

Cuando miro los datos de solicitud obtengo lo siguiente:

Processing DoodlesController#create (for 127.0.0.1 at 2010-06-28 22:51:57) [POST] Parameters: {"Filename"=>"doodle.png", "authenticity_token"=>"4UoCgzNbH1UccJbqV4P+R1mCuLk54fWTXxkZvVBin+I=", "doodle"=>{"x"=>"0", "y"=>"100", "width"=>"1024", "height"=>"768", "rotation"=>"0", "day_id"=>"16", "privacy"=>"meonly", "canvas_height"=>"1298", "canvas_width"=>"2560", "photo"=>#<File:/var/folders/RH/RHekFGKME9uDJbX4d4DG3E+++TI/-Tmp-/RackMultipart20100628-1685-1v2epqd-0>}, "commit"=>"Create"}

Que es muy similar a los datos de solicitud HTML (si utilizo la página HTML en lugar de Flex):

Processing DoodlesController#create (for 127.0.0.1 at 2010-06-28 21:55:23) [POST] Parameters: {"authenticity_token"=>"4UoCgzNbH1UccJbqV4P+R1mCuLk54fWTXxkZvVBin+I=", "doodle"=>{"privacy"=>"myonly", "day_id"=>"1", "x"=>"10", "y"=>"10", "width"=>"1000", "height"=>"1000", "rotation"=>"0", "canvas_height"=>"1000", "canvas_width"=>"1000", "photo"=>#<File:/var/folders/RH/RHekFGKME9uDJbX4d4DG3E+++TI/-Tmp-/RackMultipart20100628-1685-1gnfm5q-0>}, "commit"=>"Create"}

Lo que funciona!

y si escribo (en Mac)

open /var/folders/RH/RHekFGKME9uDJbX4d4DG3E+++TI/-Tmp-/RackMultipart20100628-1685-1v2epqd-0

(para el archivo temporal) Abre el archivo PNG previsto !!

¿Alguna sugerencia sobre cómo puedo hacer que esto funcione?


Después de tirar de mi cabello por bastante tiempo. ¡Me di cuenta de que el problema era muy tonto!

Puse un código de depuración dentro del plugin Paperclip (Justo donde la traza inversa indica el error:

vendor/plugins/paperclip/lib/paperclip/iostream.rb:8:in `extname''

y noté una línea como esta

name = respond_to?(:original_filename) ? original_filename : (respond_to?(:path) ? path : "stream")

Después de imprimir algunas variables de depuración, me di cuenta de que original_filename es nil, lo cual no debería ser como debería ser el nombre real del archivo cargado en el servidor, que se supone que es doodle.png según mi código. Solo para descubrir que olvidé un espacio antes de ''nombre de archivo'' en los datos que estaba enviando. Entonces mi código:

''Content-Disposition: form-data; name="{1}[photo]";'' + ''filename="{0}"'' + lf + ''Content-Type: application/octet-stream'' + lf + lf

Está Mal. Este código:

''Content-Disposition: form-data; name="{1}[photo]"; '' + //note extra space added here ''filename="{0}"'' + lf + ''Content-Type: application/octet-stream'' + lf + lf

Trabajos. ¡Eso es!