Base64 upload from Android/Java to RoR Carrierwave(从 Android/Java 上传 Base64 到 RoR Carrierwave)
问题描述
我添加了 将 base64 图像与 Carrierwave 结合使用的解决方案,以便上传来自 java 类的图像.这就是我的 FileUploader 类现在的样子——我相信问题出在:
I added the solution from use base64 image with Carrierwave in an effort to upload an image from a java class. This is now what my FileUploader class looks like -- and I believe to be where the problem is:
# 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
现在进行 Post 调用时,保存在 db 中的文件路径为零 - 但其他所有内容都已保存.这是java/android类:
Right now when the Post call is made the file path that is saved in the db is nil -- but everything else is saved. Here is the java/android class:
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 图像.
Does anyone have any ideas? I've been stuck on this all day. I think because I don't know much about Ruby I am either (1) malforming the request; or (2) I implemented the base64 image with Carrierwave incorrectly.
推荐答案
终于解决了问题!我希望这个答案能帮助其他试图解决这个问题的人,因为没有好的资源.这令人惊讶,因为我认为其他人也会想做同样的事情.我对 Carrierwave 初始化文件的原始更改似乎是死路一条.
Finally solved the problem! I hope this answer helps out others who are trying to solve this problem as there is no good resource for it. This was surprising as I figured others would have wanted to do the same. My original changes to the Carrierwave initialize file appear to have been a dead end.
归根结底是在控制器中创建上传的图像对象,然后将其注入回参数中.
What it came down to was creating that uploaded image object in the controller and then injecting it back into the params.
对于这个特定的示例,我们正在获取一个 base64 文件(我假设您有,因为 JSON 不支持嵌入文件)并将其保存为系统中的临时文件,然后我们正在创建 UploadedFile 对象并最终重新注入它进入参数.
For this specific example, we are taking a base64 file (which I assume you have, as JSON doesn't support embeded files) and saving it as a temp file in the system then we are creating that UploadedFile object and finally reinjecting it into the params.
我的 json/params 是什么样的:
What my json/params looks like:
picture {:user_id => "1", :folder_id => 1, etc., :picture_path {:file => "base64 awesomeness", :original_filename => "my file name", :filename => "my file name"}}
这是我的控制器现在的样子:
Here is what my controller looks like now:
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
The only thing left to do at this point is to delete the tempfile, which I believe can be done with tempfile.delete
我希望这对您的问题有所帮助!我昨天花了一整天的时间寻找解决方案,而我所看到的一切都是死胡同.但是,这适用于我的测试用例.
I hope this helps with your question! I spent all day looking for a solution yesterday, and everything I have seen is a dead end. This, however, works on my test cases.
这篇关于从 Android/Java 上传 Base64 到 RoR Carrierwave的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:从 Android/Java 上传 Base64 到 RoR Carrierwave
基础教程推荐
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 降序排序:Java Map 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01