通过Retrofit从内存上传位图

时间:2018-02-15 16:21:27

标签: android post retrofit

我想:

  1. 从图库或相机加载文件。
  2. 调整大小。
  3. 通过Retrofit将Bitmap上传到服务器,请求“/ api / file”。
  4. 1和2,我想上传Bitmap。此请求是POST(接受:application / json,Content-Type:multipart / form-data)。它接收文件作为文件,而不是文本。

    我找到了很多主题,例如https://futurestud.io/tutorials/retrofit-2-how-to-upload-files-to-serverHow to POST a bitmap to a server using Retrofit/AndroidHow to Upload Image file in Retrofit 2,但没有找不到:

    1)我应该将Bitmap从内存中保存到文件并上传,

    2)或者我可以使用Retrofit将其作为字节数组或流从内存上传吗?

    如果是2,我该如何写请求?

1 个答案:

答案 0 :(得分:1)

根据图像的大小,您当然可以将其转换为Base64编码,并在正文中使用标准的上传内容。

如果你要上传大文件,那么你应该坚持使用多部分上传,在这种情况下它将作为一个文件,但你必须指定文件的类型,API需要适当地解析它。有许多很棒的图书馆可以帮助你,比如OKHTTP,Retro也会使用它。

但是图片,文档,视频都只是转移级别的文件,只需要在调用中为图像添加适当的请求类型,以帮助API正确处理。

这是来自他们的教程:

   HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

// Change base URL to your upload server URL.
service = new Retrofit.Builder().baseUrl("http://192.168.0.234:3000").client(client).build().create(Service.class);

.
.
.

File file = new File(filePath);

RequestBody reqFile = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("upload", file.getName(), reqFile);
RequestBody name = RequestBody.create(MediaType.parse("text/plain"), "upload_test");

retrofit2.Call<okhttp3.ResponseBody> req = service.postImage(body, name);
req.enqueue(new Callback<ResponseBody>() {
    @Override
    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { 
        // Do Something
    }

    @Override
    public void onFailure(Call<ResponseBody> call, Throwable t) {
        t.printStackTrace();
    }
});

Base64Encoded如果你的文件不是太大。

    public class Base64EncodeMediaAsyncTask extends AsyncTask<Void, Void, MediaModel> {

    /*///////////////////////////////////////////////////////////////
    // MEMBERS
    *////////////////////////////////////////////////////////////////
    private static final String TAG = Globals.SEARCH_STRING + Base64EncodeMediaAsyncTask.class.getSimpleName();
    private Context mContext;
    private MediaModel mMediaModelToConvert;


    /*///////////////////////////////////////////////////////////////
    // CONSTRUCTOR
    *////////////////////////////////////////////////////////////////
    public Base64EncodeMediaAsyncTask(Context context, MediaModel model){
        mContext = context;
        mMediaModelToConvert = model;

    }


    /*///////////////////////////////////////////////////////////////
    // OVERRIDES
    *////////////////////////////////////////////////////////////////
    @Override
    protected MediaModel doInBackground(Void... params) {
        try{
            InputStream inputStream = new FileInputStream(mMediaModelToConvert.getAbsoluteLocalPath());//You can get an inputStream using any IO API
            byte[] bytes;
            byte[] buffer = new byte[(int) new File(mMediaModelToConvert.getAbsoluteLocalPath()).length()];
            int bytesRead;

            ByteArrayOutputStream output = new ByteArrayOutputStream();
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                output.write(buffer, 0, bytesRead);
            }

            bytes = output.toByteArray();

            mMediaModelToConvert.setBase64String(Base64.encodeToString(bytes, Base64.DEFAULT));

        }catch (Exception ex){
            //todo consider moving failed uploads to table known for failures to let user know to delete, or validate file or try again
            A35Log.e(TAG, "Failed to get base 64 encoding for file: " + mMediaModelToConvert.getAbsoluteLocalPath());
            return null;

        }

        return mMediaModelToConvert;

    }
    @Override
    protected void onPostExecute(MediaModel success) {
        super.onPostExecute(success);

    }

}

只需忽略MediaModel,它是我用于包装其他内容的复杂对象,只需使用标准文件(也就是指向图像的指针)