2010-09-24 31 views
0

La question est juste au-dessus du dernier extrait de code. Je vous remercie. (détails de l'environnement sont la fin)peut partie HTTP multipart/mix xml être converti en un Hash lorsqu'il est mélangé avec d'autres parties

posts_controller.rb

class PostsController < ApplicationController 
def create 
    @post = Post.new(params[:post]) 
    respond_to do |format| 
     format.xml { render :xml => @post.to_xml(:include => [ :assets])} 
end 
end 

posts.rb

class Post < ActiveRecord::Base 
    has_many :assets, :as => :attachable, :dependent => :destroy 
end 

asset.rb

class Asset < ActiveRecord::Base 
    belongs_to :attachable, :polymorphic => true 
    has_attached_file :data, 
        :url => "/assets/:id", 
        :path =>":rails_root/assets/:id_partition/:style/:basename.:extension" 
    def name 
    data_file_name 
    end 

    def content_type 
    data_content_type 
    end 

    def file_size 
    data_file_size 
    end 
    end 

maintenant quand nous affichons ces informations

POST /posts.xml HTTP/1.1 
Accept-Encoding: gzip,deflate 
Accept: application/xml 
Content-Type: application/xml 
User-Agent: Jakarta Commons-HttpClient/3.1 
Host: localhost:8080 
Content-Length: 60 

<post><body>postbody</body><title>post_title</title></post> 

une entrée de poste est créé et quand je poste ce

POST /posts.xml HTTP/1.1 
Content-type: multipart/mixed; boundary=---------------------------7d226f700d0 
Accept: application/xml,text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
Cache-Control: no-cache 
Pragma: no-cache 
User-Agent: Java/1.6.0_21 
Host: 192.168.0.105:8080 
Connection: keep-alive 
Content-Length: 1710 

-----------------------------7d226f700d0 
content-disposition: form-data; name="post[title]" 
Content-Length: 10 
post_title 
-----------------------------7d226f700d0 
content-disposition: form-data; name="post[body]" 
Content-Length: 8 
postbody 
-----------------------------7d226f700d0 
content-disposition: form-data; name="post[assets_attributes][0][data]"; filename="C:/Users/mv288/files/1.txt" 
content-type: application/octet-stream 
ÿþ 
sample file content 
-----------------------------7d226f700d0 
content-disposition: form-data; name="post[assets_attributes][0][data]"; filename="C:/Users/mv288/Pictures/1.txt" 
content-type: application/octet-stream 
ÿþ 
sample file content 
-----------------------------7d226f700d0 

un nouveau poste est créé avec 2 pièces jointes.

maintenant la question est, je veux obtenir le poste HTTP suivant (s'il vous plaît noter la partie xml avant que les pièces jointes) pour créer également un poste avec 2 pièces jointes, sans modifications supplémentaires (à posts_controller ou routes.rb). est-ce possible?

POST /posts.xml HTTP/1.1 
Content-type: multipart/mixed; boundary=---------------------------7d226f700d0 
Accept: application/xml,text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
Cache-Control: no-cache 
Pragma: no-cache 
User-Agent: Java/1.6.0_21 
Host: 192.168.0.105:8080 
Connection: keep-alive 
Content-Length: 1710 

-----------------------------7d226f700d0 
Content-type: application/xml; charset=UTF-8 
Content-Length: 59 
<post><body>postbody</body><title>post_title</title></post> 
-----------------------------7d226f700d0 
content-disposition: form-data; name="post[assets_attributes][0][data]"; filename="C:/Users/mv288/files/1.txt" 
content-type: application/octet-stream 
ÿþ 
sample file content 
-----------------------------7d226f700d0 
content-disposition: form-data; name="post[assets_attributes][0][data]"; filename="C:/Users/mv288/Pictures/1.txt" 
content-type: application/octet-stream 
ÿþ 
sample file content 
-----------------------------7d226f700d0Blockquotetest 

utilisant JRuby 1.5.2/jdk1.6, rails 2.3.4, 2.3.3-paperclip sur Windows 2007-64 bits

Répondre

0

rails au moins ne fait pas 2.3.4 cette automatiquement. Il faut écrire un analyseur multipart/related et l'enregistrer, dans les initializers/mime_types.rb

NOTE: N'hésitez pas à mettre à jour les valeurs codées en dur (comme le préfixe de pièce principale et de pièce jointe, etc.) dans votre copie.

Cette même stratégie peut également être utilisée pour le contenu multipart/associé. Nous débattons encore de l'utilisation de multipart/related ou multipart/mixed dans cet exemple ci-dessous.

Notes de Microsoft sur ce sujet. http://msdn.microsoft.com/en-us/library/ms527355(EXCHG.10).aspx

Mime::Type.register "multipart/mixed", :mixed 

class ActionController::Request 
    def initialize(env) 
    Thread.current[:request]=self 
    super 
    end 

end 

class MultiPartParamsParser 

    def main_part_name 
    "main" 
    end 

    def attachment_part_prefix 
    "my_company_attachment" 
    end 

    def content_type(main_part) 
    # TODO ---- 
    :xml_simple 
    end 

    def content(main_part) 
    # TODO implement this 
    if main_part.is_a?(String) 
     main_part.gsub!("Content-Type: application/xml",'') # remove content type if it exists 
     main_part.strip! # to remove any trailing or leading whitespaces 
    else 
     main_part[:tempfile].read 
    end 
    end 

    def request 
    Thread.current[:request] 
    end 

    def parse_formatted_parameters(data) 
    multi_parts = Rack::Utils::Multipart.parse_multipart(request.try(:env)) 
    main_part = multi_parts[main_part_name] 
    data  = content(main_part) 
    # TODO return an error if data is not found 
    params = case content_type(main_part) 
     when :xml_simple, :xml_node 
     data.blank? ? {} : Hash.from_xml(data).with_indifferent_access 
     when :yaml 
     YAML.load(data) 
     when :json 
     if data.blank? 
      {} 
     else 
      ret = ActiveSupport::JSON.decode(data) 
      ret = {:_json => data} unless data.is_a?(Hash) 
      ret.with_indifferent_access 
     end 
     else 
     {} 
    end 
    process_attachments(params, multi_parts) 
    params     
    end 

    def process_attachments(data, multi_parts) 
    data.each do |key, value| 
     value ||= key # when array value is nil 
     if value.is_a?(Hash) or value.is_a?(Array) 
     process_attachments(value, multi_parts) 
     elsif value.respond_to?(:match) and value.match("^#{attachment_part_prefix}") and (attachment=multi_parts[value]) # there could Time,Numbers etc.., but we match only string. 
     data[key] = create_uploaded_file(attachment) # TODO handle the scenarios for short strings 
     end 
    end   
    end 

    def create_uploaded_file (attachment) 
    upload = attachment[:tempfile] 
    upload.extend(ActionController::UploadedFile) 
    upload.original_path = attachment[:filename] 
    upload.content_type = attachment[:type] 
    upload 
    end 
end 

proc = Proc.new do |data| 
    MultiPartParamsParser.new.parse_formatted_parameters(data) 
end 

ActionController::Base.param_parsers[Mime::Type.lookup('multipart/mixed')] = proc 

alors, vous pouvez poster votre message comme celui-ci. L'imbrication est automatiquement prise sans autre modification des modèles ou des contrôleurs.

POST /posts.xml HTTP/1.1 
Content-type: multipart/mixed; boundary=---------------------------###987612345### 
Accept: application/xml,text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2 
Cache-Control: no-cache 
Pragma: no-cache 
Connection: keep-alive 
Content-Length: ## 

-----------------------------###987612345### 
content-disposition: name="main" 
Content-Length: ## 
<post><title>post_title</title><body>post_body</body> 
    <assets_attributes type="array"> 
      <asset><data>my_company_attachment_0</data> </asset> 
      <asset><data>my_company_attachment_1</data> </asset> 
    </assets_attributes> 
</post> 
-----------------------------###987612345### 
content-disposition: name="my_company_attachment_0"; filename="C:/Users/mv288/files/1.txt" 
content-type: application/octet-stream 
ÿþ 
sample file content 
-----------------------------###987612345### 
content-disposition: name="my_company_attachment_1"; filename="C:/Users/mv288/Pictures/1.png" 
content-type: image/png 
ÿþ 
sample file content 
-----------------------------###987612345###