还是上次的需求,让做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了。
可能实现的不好,求高人指点更好的解法。