我正在尝试使用以下代码(来自Flex on Rails书籍)将动态生成的文件从Flex(PNG图像)上传到Ruby 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); }
和getMultiPartRequestData函数是:
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,_model.current_day.id,privacyGroup.selectedValue.toString(),FlexGlobals.topLevelApplication.height,FlexGlobals.topLevelApplication.width),"ascii"); result.writeBytes(bytes,bytes.length); result.writeMultiByte(part2,"ascii"); return result; }
我得到以下异常:
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'
当我查看请求数据时,我得到以下内容:
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"}
这与HTML请求数据非常相似(如果我使用HTML页面而不是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","canvas_height"=>"1000","canvas_width"=>"1000","photo"=>#<File:/var/folders/RH/RHekFGKME9uDJbX4d4DG3E+++TI/-Tmp-/RackMultipart20100628-1685-1gnfm5q-0>},"commit"=>"Create"}
哪个有用!
如果我输入(在Mac中)
open /var/folders/RH/RHekFGKME9uDJbX4d4DG3E+++TI/-Tmp-/RackMultipart20100628-1685-1v2epqd-0
有关如何使其工作的任何建议?
解决方法
拉了我的头发很长一段时间后.我意识到问题非常愚蠢!
我在Paperclip插件中放置了一个调试代码(在回溯声明错误的地方:
vendor/plugins/paperclip/lib/paperclip/iostream.rb:8:in `extname'
我注意到这样的一条线
name = respond_to?(:original_filename) ? original_filename : (respond_to?(:path) ? path : "stream")
在打印出一些调试变量后,我意识到original_filename是nil,不应该是因为应该是根据我的代码上传到服务器的实际文件名应该是doodle.png.只是发现我在发送的数据中的’filename’之前忘记了一个空格.所以我的代码:
'Content-Disposition: form-data; name="{1}[photo]";' + 'filename="{0}"' + lf + 'Content-Type: application/octet-stream' + lf + lf
是错的.这段代码:
'Content-Disposition: form-data; name="{1}[photo]"; ' + //note extra space added here 'filename="{0}"' + lf + 'Content-Type: application/octet-stream' + lf + lf
作品.而已!