至少Rails2.3.4不会自动执行此操作。我们需要在initializers/mime中编写一个多部分/相关的解析器并注册它_类型.rb
注意:请随时更新副本中的硬编码值(如主和附件部分前缀等)。
同样的策略也可以用于多部分/相关内容。在下面的示例中,我们仍在讨论是使用multipart/related还是multipart/mixed。
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###