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)