3

I want to:

  1. Load a file from gallery or camera.
  2. Resize it.
  3. Upload gotten Bitmap to a server with request like "/api/file" via Retrofit.

1 and 2 are made, I want to upload Bitmap. This request is POST (Accept: application/json, Content-Type: multipart/form-data). It receives files as a file, not text.

I found many topics like https://futurestud.io/tutorials/retrofit-2-how-to-upload-files-to-server, How to POST a bitmap to a server using Retrofit/Android, How to Upload Image file in Retrofit 2, but don't undestand:

1) should I save a Bitmap from memory to a file and upload,

2) or can I upload it from memory as byte array or stream using Retrofit?

If 2, how can I write a request?

6
  • stackoverflow.com/questions/31325723/… you can try this.. Commented Feb 15, 2018 at 16:29
  • try the 2nd answer..of the post.. Commented Feb 15, 2018 at 16:30
  • @SantanuSur, thanks, probably I will try. Commented Feb 15, 2018 at 16:31
  • You should first tell us in which way the server wants to receive your image. Only then can we advice how to do it. It makes no sense to send base64 if the server wants a jpg file. Commented Feb 15, 2018 at 17:00
  • @greenapps, probably it expects a JPEG file, but this is not a restriction (I think, several types of images can be loaded). As far as I know, Base64 format is supported in our server. What else can I add to a question? Commented Feb 15, 2018 at 17:08

1 Answer 1

1

Depending on the size of the image you can certainly convert it to Base64 encoded and use a standard upload content in the body.

If you are uploading large files then you should stick with multi-part uploads, in which case it will go as a file, but you have to specify the type of file and the API needs to parse it appropriately. There are many great libraries to help you with this like OKHTTP, which Retro will also utilize.

But images, docs, videos, are all just files at the transfer level, it's just a matter of putting appropriate request types for image in your call to help the API handle appropriately.

This is from their tutorial below:

   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 if you aren't too large of a file.

    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);

    }

}

Just ignore the MediaModel that is a complex object I have for wrapping additional content, just use a standard File (aka pointer to your image)

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks. If i convert to Base64 (stackoverflow.com/questions/9224056/…), can I upload this string in body?
Yup, I will even give you a snippet hold please :)
Updated see latest
Thanks. I think a server doesn't accept text in Base64, only files. So I will try other ways to upload.
Coolmind, you have to do a normal post or put with XML or json body where one of the elements is the base64 encoded string. Sorry if I confused you with that. It's just an element of the body that you put in and parse out on the server side. Multipart upload expects files
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.