在Ruby on Rails 中用 xmlrpc 來傳輸附件(圖片)

還是上次的需求,讓做Bugzilla的WebService的擴展,Bugzilla的WebService API 中只有create bug的API(不帶附件的),現在費讓我做一個在創建的時候可以帶attachment的API。

 

在網上找了下,沒看到xmlrpc還可以傳attachment的例子,都說可以傳字符串,數字等基本類型。

 

但是我想傳圖片怎麼整呢?

 

1.我先將圖片轉化成2進制流

2.再將2進制流轉化成base64的字編碼

3.用xmlrpc把base64編碼傳輸過去(當string傳過去)

4.在server端在base64給decode了

5.讓後就可以直接當BLOB類型存入mysql數據庫了

 

PS:我沒考慮效率之類的,我就先找個方法來實現我的需求,因爲把2進制流變成base64編碼的時候文件在無形中就變大了。

 

代碼如下:

 

1.erb文件

<% form_tag({:action=>'upload'},:multipart => true) do%>
      <label for="file">File to Upload</label> 
      <%= file_field_tag "file" %>
      <%=submit_tag "upload" %>
<% end %>
 

2.controller文件中

require "xmlrpc/client"
require "base64"
class SoapController < ApplicationController
  before_filter :get_XMLRPC_server
  
  def index
    @products_arr = get_products()
  end
  
  def rcp

    @result_1= @server.call("Bugzilla.version")
    @result_2= @server.call("Bugzilla.timezone")
    @result_3= @server.call("Bug.get",{:ids=>[1]})
    @result_4= @server.call("Bug.add_attachment",{:id=>1})
   
    render :action=>'index'
  end
  
  def new_bug
    @product_name = params[:product_name]
  end
  
  def create_bug
    
    bug = {
        :product     => params[:p], 
        :component   => params[:component],
        :summary     => params[:summary],
        :version     => 'unspecified',
        :description => params[:description],
        :op_sys      => params[:op_sys],
        :platform    => params[:platform],   
        :priority    => params[:priority],
        :severity    => params[:severity]
    }
    
    @server.call("Bug.create",bug)
    
    redirect_to :action=>'index'
  end
  
  def upload
    file = params[:file]
    file_name = file.original_filename
    data = encode64(file.read)
    @server.call("Bug.add_attachment",{:id=>1,:data=>data,:filename=>file_name})
  end
  
private 
 
  def login_bugzilla(name,pass,is_remember)
    
     loginInfo= {
      :login=>name,
      :password => pass,
      :remember => is_remember 
    }
    
    return  @server.call("User.login",loginInfo)
  end
  
  def get_XMLRPC_server
    @server =  XMLRPC::Client.new( "192.168.1.37", "/bugzilla/xmlrpc.cgi")
    login_bugzilla('[email protected]','111111',false)
  end
  
  def get_products
    ids = @server.call('Product.get_selectable_products')
    p = @server.call('Product.get',ids)
    return p["products"]
  end

end

 3.在Bugzilla的下的/Bugzilla/WebService/Bug.pm文件下加入擴展的API

首先 
use MIME::Base64;

sub add_attachment {
    my ($self,$params) = @_ ;

    my $user = Bugzilla->login(LOGIN_REQUIRED);

    defined $params->{id} || ThrowCodeError('param_required', { param => 'id' }); 
    defined $params->{data} || ThrowCodeError('param_required', { param => 'data' }); 
    defined $params->{filename} || ThrowCodeError('param_required', { param => 'filename' });

    my $bug = Bugzilla::Bug->check($params->{id});

    Bugzilla->user->can_edit_product($bug->product_id) || ThrowUserError("product_edit_denied", {product => $bug->product});

    my $dbh = Bugzilla->dbh;
    my ($timestamp) = $dbh->selectrow_array("SELECT NOW()");

    my $data = decode_base64($params->{data});
    my $filename = $params->{filename};
    my $description = "test from xmlrpc";
    my $contenttype = "image/jpeg";
    my $isurl = 0;
    my $isprivate = 0;

    $dbh->bz_start_transaction();

     my $sth = $dbh->do(
        "INSERT INTO attachments
            (bug_id, creation_ts, modification_time, filename, description,
             mimetype, ispatch, isurl, isprivate, submitter_id)
         VALUES (?,?,?,?,?,?,?,?,?,?)", undef, ($bug->bug_id, $timestamp, $timestamp,
              $filename, $description, $contenttype, 0,
              $isurl, $isprivate, $user->id));
    # Retrieve the ID of the newly created attachment record.
    my $attachid = $dbh->bz_last_key('attachments', 'attach_id');

    # We only use $data here in this INSERT with a placeholder,
    # so it's safe.
    $sth = $dbh->prepare("INSERT INTO attach_data
                         (id, thedata) VALUES ($attachid, ?)");
    trick_taint($data);
    $sth->bind_param(1, $data, $dbh->BLOB_TYPE);
    $sth->execute();
 
    
    $dbh->bz_commit_transaction();
    

    return { at => $data };
}

 

以上就實現了怎麼可以給一個現有的bug添加一個attachment了。

 

可能實現的不好,求高人指點更好的解法。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章