2012-03-24 11 views
7

Javaクラスから画像をアップロードするために、use base64 image with Carrierwaveから解決策を追加しました。これは私のFileUploaderクラスがどのように見えるか、今ある - そして私は、問題がどこにあるかであると信じる:Android/JavaからRoRへのBase64アップロードCarrierwave

# encoding: utf-8 

class FileUploader < CarrierWave::Uploader::Base 

    # Include RMagick or MiniMagick support: 
    include CarrierWave::RMagick 
    # include CarrierWave::MiniMagick 

    # Choose what kind of storage to use for this uploader: 
    storage :file 
    # storage :fog 

    #START FROM BASE64 POST LINKED ABOVE 
    class FilelessIO < StringIO 
    attr_accessor :original_filename 
    attr_accessor :content_type 
    end 

    before :cache, :convert_base64 

    def convert_base64(file) 
    if file.respond_to?(:original_filename) && 
     file.original_filename.match(/^base64:/) 
     fname = file.original_filename.gsub(/^base64:/, '') 
     ctype = file.content_type 
     decoded = Base64.decode64(file.read) 
     file.file.tempfile.close! 
     decoded = FilelessIO.new(decoded) 
     decoded.original_filename = fname 
     decoded.content_type = ctype 
     file.__send__ :file=, decoded 
    end 
    file 
    end 
#END FROM POST LINKED ABOVE 


    # Override the directory where uploaded files will be stored. 
    # This is a sensible default for uploaders that are meant to be mounted: 
    def store_dir 
    "uploads/#{model.class.to_s.underscore}/#{model.user_id}" 
    end 

    # Provide a default URL as a default if there hasn't been a file uploaded: 
    # def default_url 
    # "/images/fallback/" + [version_name, "default.png"].compact.join('_') 
    # end 

    # Process files as they are uploaded: 
    # process :scale => [200, 300] 
    # 
    # def scale(width, height) 
    # # do something 
    # end 

    # Create different versions of your uploaded files: 
    version :thumb do 
     process :resize_to_fit => [200, 300] 
    end 

    version :web do 
     process :resize_to_fit => [1000, 1000] 
    end 

    # Add a white list of extensions which are allowed to be uploaded. 
    # For images you might use something like this: 
    def extension_white_list 
    %w(jpg jpeg gif png) 
    end 

    # Override the filename of the uploaded files: 
    # Avoid using model.id or version_name here, see uploader/store.rb for details. 
    def filename 
    if original_filename 
    Time.new.to_i.to_s+"_"+original_filename 
    end 
    end 

end 

画像モデル:今ポストコールは、ファイルパスをしたとき

class Picture < ActiveRecord::Base 

    belongs_to :user 
    belongs_to :folders 

    attr_accessible :user_id, :picture_name, :picture_description, 
    :folder_id, :picture_path, :file_save 

    mount_uploader :picture_path, FileUploader 

    before_save :update_pictures_attributes 

    def update_pictures_attributes 
     self.file_size = picture_path.file.size 
    end 

end 

dbに保存されているものはゼロですが、それ以外はすべて保存されます。ここにjava/androidクラスがあります:

import java.io.File; 
import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 

import org.apache.http.client.*; 
import org.apache.http.client.entity.*; 
import org.apache.http.client.methods.*; 
import org.apache.http.entity.StringEntity; 
import org.apache.http.impl.client.*; 
import org.apache.http.message.*; 
import org.apache.commons.io.FileUtils; 
import org.json.*; 
import android.util.Base64; 
import android.util.Log; 

public class Uploader { 

    private String url; 
    private String fileName; 

    public Uploader(String url, String fileName){ 
     this.url = url; 
     this.fileName = fileName; 
    } 

    public Boolean upload() throws JSONException, ClientProtocolException, IOException { 
     Boolean success = true; 
     JSONObject jsonObject = constructPictureJson(); 
      DefaultHttpClient httpClient = new DefaultHttpClient(); 

      ResponseHandler <String> responseHandler = new BasicResponseHandler(); 
      HttpPost postMethod = new HttpPost(url); 
      postMethod.setEntity(new StringEntity(jsonObject.toString())); 
      postMethod.setHeader("Accept", "application/json"); 
      postMethod.setHeader("Content-type", "application/json"); 
      postMethod.setHeader("Data-type", "json"); 
      try{ 
      httpClient.execute(postMethod, responseHandler); 
      } catch (org.apache.http.client.HttpResponseException error){ 
       Log.d("Uploader Class Error", "Error code: "+error.getStatusCode()); 
       Log.d("Uploader Class Error", "Error message: "+error.getMessage()); 
       success = false; 
      } 
      //Log.d("server resposne", response); 
      return success; 
    } 

    public JSONObject constructPictureJson() throws JSONException, IOException{ 
     String userId = "1"; 
     String folderId = "1"; 
     String[] file = fileName.split("/"); 
     JSONObject pictureData = new JSONObject(); 
     pictureData.put("user_id", userId); 
     pictureData.put("folder_id", folderId); 
     pictureData.put("picture_name", "picture name"); 
     pictureData.put("picture_description", "1"); 
     pictureData.put("content_type", "jpg"); 
     pictureData.put("original_filename", "base64:"+file[file.length-1]); 
     pictureData.put("filename", file[file.length-1]); 
     pictureData.put("picture_path", encodePicture(fileName)); 

     return pictureData; 
    } 

    public String encodePicture(String fileName) throws IOException{ 
     File picture = new File(fileName); 
     return Base64.encodeToString(FileUtils.readFileToByteArray(picture), Base64.DEFAULT); 
    } 

} 

誰にでもアイデアはありますか?私は一日中このままで立ち往生してきました。私はRubyについてあまり知らないので、私は(1)リクエストの不正な形式か、または(2)Carrierwaveでbase64イメージを間違って実装しました。

答えて

19

最後に問題を解決しました。私は、この回答が、この問題を解決しようとしている他の人に役立つことを願っています。私は他の人が同じことをしたいと思ったので、これは驚くべきことでした。 Carrierwave初期化ファイルへの私の元の変更は、行き詰まっているようです。

アップロードされたイメージオブジェクトをコントローラーに作成し、それをパラメーターに注入して戻したのは何ですか?

この具体例では、JSONが埋め込みファイルをサポートしていないため、base64ファイルを取得してシステムに一時ファイルとして保存してから、そのUploadedFileオブジェクトを作成していますそれをパラメータに再注入する。どのように見えるか、私のJSON/paramsは

:ここ

picture {:user_id => "1", :folder_id => 1, etc., :picture_path {:file => "base64 awesomeness", :original_filename => "my file name", :filename => "my file name"}} 

は私のコントローラは、今のように見えるものです:

40  # POST /pictures 
41 # POST /pictures.json 
42 def create 
43 
44  #check if file is within picture_path 
45  if params[:picture][:picture_path]["file"] 
46   picture_path_params = params[:picture][:picture_path] 
47   #create a new tempfile named fileupload 
48   tempfile = Tempfile.new("fileupload") 
49   tempfile.binmode 
50   #get the file and decode it with base64 then write it to the tempfile 
51   tempfile.write(Base64.decode64(picture_path_params["file"])) 
52  
53   #create a new uploaded file 
54   uploaded_file = ActionDispatch::Http::UploadedFile.new(:tempfile => tempfile, :filename => picture_path_params["filename"], :original_filename => picture_path_params["original_filename"]) 
55  
56   #replace picture_path with the new uploaded file 
57   params[:picture][:picture_path] = uploaded_file 
58  
59  end 
60 
61  @picture = Picture.new(params[:picture]) 
62 
63  respond_to do |format| 
64  if @picture.save 
65   format.html { redirect_to @picture, notice: 'Picture was successfully created.' } 
66   format.json { render json: @picture, status: :created, location: @picture } 
67  else 
68   format.html { render action: "new" } 
69   format.json { render json: @picture.errors, status: :unprocessable_entity } 
70  end 
71  end 
72 end 

唯一のことは、この時点で行うには、左の一時ファイルを削除することで、私はこれができると信じていますtempfile.delete

私はこれがあなたの質問に役立つことを願っています!昨日、私は一日中解決策を探していました。私が見てきたことはすべて終わりです。しかし、これは私のテストケースで動作します。

+1

これは素晴らしい結果でした。ありがとう。私は、before_filter:process_attached_file、only::create'コールにparamsの処理を入れて、createメソッドをよりきれいに保つのを助けました。 –

+3

私は同じことをしようとしています。あなたのアンドロイドアプリの最終的なJavaコードを投稿できますか? – scientiffic

+0

アンドロイド側のアップロード機能の最終実装を共有してもよろしいですか?私も同様のことをしていますが、私もRailsを使用していますが、実際のアップロードは非常に遅いです - 私はwebrickでテストしていると仮定していますが、イメージを縮小したか、アップロードする前に – Riptyde4

関連する問題