2010-09-24 1 views
0

Вопрос находится чуть выше последнего фрагмента кода. Спасибо. (детали окружения являются конечным)может быть преобразован в хэш-файл HTTP multipart/mixed xml в хэш-код при смешивании с другими частями

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 

теперь, когда мы размещаем эту информацию

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> 

записи после получает создана и когда я отправляю этот

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 

новый пост будет создаваться с 2 прикрепленными файлами.

теперь вопрос, я хочу, чтобы получить следующий HTTP пост (пожалуйста, обратите внимание на XML часть перед вложенными файлами) также создать пост с 2 вложений, без каких-либо дополнительных изменений (в posts_controller или routes.rb). это возможно?

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 

с использованием JRuby 1.5.2/jdk1.6, рельсы 2.3.4, скрепка-2.3.3 на окнах 2007 - 64 бит

ответ

0

По крайней мере, рельсы 2.3.4 не делает этого автоматически. Нужно написать многопараметрический парсер и зарегистрировать его, внутри инициализаторов/mime_types.rb

ПРИМЕЧАНИЕ. Не стесняйтесь обновлять жестко закодированные значения (например, префикс основной и прикрепленной части и т. Д.) В вашей копии.

Эта же стратегия может быть использована и для multipart/related content. Мы по-прежнему обсуждаем, использовать ли в этом примере несколько multipart/related или multipart/mixed.

Заметки Microsoft по этому вопросу. 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 

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

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###