代码之家  ›  专栏  ›  技术社区  ›  so_mv

Archiloque REST客户机:设置文件位置时,将内容类型更改为multipart/related

  •  0
  • so_mv  · 技术社区  · 14 年前

    使用 http://github.com/archiloque/rest-client

    使用此行发布文件时,内容类型设置为

    Content-Type: multipart/form-data; boundary=301405
    

    默认情况下,在标题中。

    RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
    

    我尝试了这个方法,它仍然设置头多部分/表单数据。

    RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb'), :content_type => 'multipart/related'
    

    是否有人尝试设置多部分/相关?

    2 回复  |  直到 14 年前
        1
  •  1
  •   paul.belt    14 年前
        2
  •  0
  •   so_mv    14 年前

    好啊。我找不到更好的选择,所以最终使用了以下应用程序。

    它基于这里的代码。 http://stanislavvitvitskiy.blogspot.com/2008/12/multipart-post-in-ruby.html

    用途:

    files = { File.new("myfile1","rb"), File.new("myfile2","rb")}
    mpost = Mutipart("main", "<my xml main part content which refers to file names>",files )
    mpost.post("our_url","post")
    

    注: 此代码未准备好生产。它只是功能性的。

    -----------多部分.rb---------

    require 'net/http'
    require 'uri'
    require 'pp'
    require 'mime/types'
    
    class Multipart  
    
      def initialize( main_part_id, main_part_content, file_names )  
        @file_names = file_names  
        @main_part_id = main_part_id
        @main_part_content = main_part_content
      end
    
      def post( to_url, method = :post )  
        boundary = "###-------#{Time.new}-----####"
    
        parts = []  
        streams = []
        # write main part first
        parts << StringPart.new( "--" + boundary + "\r\n")
        parts << StringPart.new("Content-Disposition: name=\"#{@main_part_id}\";\"\r\n" +  
          "Content-ID: #{@main_part_id}\r\n\r\n"+
          "Content-Type: application/xml\r\n\r\n" +  
        @main_part_content + "\r\n\r\n")
        parts << StringPart.new( "\r\n--" + boundary + "\r\n")
    
        @file_names.each do |param_name, filestream|
          raise 'mutlipartsend: empty file object' if filestream.blank?
    
          filename= filestream.respond_to?(:original_path) ? filestream.original_path : filestream.path
          ctype = filestream.respond_to?(:content_type) ? filestream.content_type: nil
          fsize = filestream.respond_to?(:lstat) ? filestream.lstat.size : filestream.size
    
    
          if !ctype
            begin
                pos = filename.rindex('/') # if filename is a path
                fname = filename[pos + 1, filename.length - pos]
                mm = MIME::Types.type_for(fname)
                ctype = mm.first.content_type if !mm.blank?
            rescue Exception => e
              p e.message
            end
          end
          if !ctype
            ctype= 'application/binary'
            p "mutlipartsend: failed to determine contenttype for #{filename}. using application/binary"
          end
    
    
          parts << StringPart.new("Content-Disposition: name=\"" + param_name.to_s + "\"; filename=\"" + filename + "\"\r\n" +  
            "Content-Type: #{ctype}\r\n\r\n")
            #"Content-Type: application/binary\r\n\r\n")
          begin
            stream = File.open(filestream.path,"rb")
            streams << stream 
            parts << StreamPart.new(stream, fsize)
            parts << StringPart.new( "\r\n--" + boundary + "\r\n" )
          rescue Exception => e
            p 'failed to load filestream '+ filestream.path
            p e.message
            raise 'failed to load filestream ' + e.message
          end
    
        end
    
        post_stream = MultipartStream.new( parts )  
    
        url = URI.parse( to_url )
        req = method == :post ? Net::HTTP::Post.new(url.path) : Net::HTTP::Put.new(url.path)
        req.content_length = post_stream.size
        req.content_type = 'multipart/mixed; boundary=' + boundary
        req["myheader1"] = 'header1'
        req["myheader2"] = 'header2'
    
        req.body_stream = post_stream  
        res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req) }  
    
        streams.each do |stream|  
          stream.close();  
        end  
    
        res  
      end  
    
    end  
    
    class StreamPart  
      def initialize( stream, size )  
        @stream, @size = stream, size  
      end  
    
      def size  
        @size  
      end  
    
      def read( offset, how_much )  
        @stream.read( how_much )  
      end  
    end  
    
    class StringPart  
      def initialize ( str )  
        @str = str  
      end  
    
      def size  
        @str.length  
      end  
    
      def read ( offset, how_much )  
        @str[offset, how_much]  
      end  
    end  
    
    class MultipartStream  
      def initialize( parts )  
        @parts = parts  
        @part_no = 0;  
        @part_offset = 0;  
      end  
    
    
    
      def size  
        total = 0  
        @parts.each do |part|  
          total += part.size  
        end  
        total  
      end  
    
      def read ( how_much )  
        if @part_no >= @parts.size  
          return nil;  
        end  
    
        how_much_current_part = @parts[@part_no].size - @part_offset  
    
        how_much_current_part = if how_much_current_part > how_much  
          how_much  
        else  
          how_much_current_part  
        end  
    
        how_much_next_part = how_much - how_much_current_part  
    
        current_part = @parts[@part_no].read(@part_offset, how_much_current_part )  
    
        if how_much_next_part > 0  
          @part_no += 1
          @part_changed=true
          @part_offset = 0  
          next_part = read( how_much_next_part  )  
          current_part + if next_part  
            next_part  
          else  
            ''  
          end  
        else  
          @part_offset += how_much_current_part  
          current_part  
        end  
      end  
    
    end
    
    推荐文章