I am trying to upload a file to WordPress using REST API. I have tried different headers, values but no luck. I have tried different clients such as okhttp and custom one such as Fast-AndroidNetworking.
I have succeeded to create new post with AndroidNetworking, but when it comes to creating/uploading new media, it does not work and does not return any response.
No luck to upload.
Following my code with AndroidNetworking.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnImage = findViewById(R.id.button);
btnImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, 1234);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ImageView imgTestImage = findViewById(R.id.imageView1);
final TextView txtTestPath = findViewById(R.id.txtTestPath);
if (resultCode == Activity.RESULT_OK)
switch (requestCode){
case 1234:
Uri uriSelectedImage = data.getData();
String imgFullPath = uriSelectedImage.getPath();
String imgPath = imgFullPath.substring(imgFullPath.lastIndexOf(":")+1);
File imgFile = new File(imgPath);
String imgName = imgFile.getName();
long imgSize = imgFile.length();
String mimType = getContentResolver().getType(uriSelectedImage);
txtTestPath.setText(imgPath +"\n"+mimType + "\n"+ imgName + " "+ String.valueOf(imgSize));
AndroidNetworking.initialize(getApplicationContext());
AndroidNetworking.post("https://test.matjri.com/wp-json/wp/v2/media")
.addFileBody(imgFile)
.addHeaders("Connection", "keep-alive")
.addHeaders("Host", "test.matjri.com")
.addHeaders("Content-Length", String.valueOf(imgSize))
.addHeaders("Cache-Control", "no-cache")
.addHeaders("Content-Type", mimType)
.addHeaders("Content-Disposition", "attachment;filename=\"" + imgName + "\"")
.addHeaders("Authorization", "Bearer mytoken")
.setTag("uploadFile")
.setPriority(Priority.MEDIUM)
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
#Override
public void onResponse(JSONObject response) {
txtTestPath.setText(response.toString());
}
#Override
public void onError(ANError anError) {
txtTestPath.setText(anError.getMessage());
}
});
imgTestImage.setImageURI(uriSelectedImage);
}
}
}
I have also tried the okhttp instead of AndroidNetworking still no luck to upload, however, I get unknown errors.
The code with okhttp
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btnImage = findViewById(R.id.button);
btnImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, 1234);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
ImageView imgTestImage = findViewById(R.id.imageView1);
final TextView txtTestPath = findViewById(R.id.txtTestPath);
if (resultCode == Activity.RESULT_OK)
switch (requestCode){
case 1234:
Uri uriSelectedImage = data.getData();
String imgFullPath = uriSelectedImage.getPath();
String imgPath = imgFullPath.substring(imgFullPath.lastIndexOf(":")+1);
File imgFile = new File(imgPath);
String imgName = imgFile.getName();
long imgSize = imgFile.length();
String mimType = getContentResolver().getType(uriSelectedImage);
txtTestPath.setText(imgPath +"\n"+mimType + "\n"+ imgName + " "+ String.valueOf(imgSize));
OkHttpClient okHttpClient = new OkHttpClient();
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
builder.addFormDataPart("file", imgPath);
String url = "https://test.matjri.com/wp-json/wp/v2/media/";
RequestBody fileBody = RequestBody.create(MediaType.parse(mimType), imgPath);
builder.addFormDataPart("file", imgName, fileBody);
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", "Bearer mytoken")
.addHeader("Content-Type", mimType)
.addHeader("Content-Length", String.valueOf(imgSize))
.addHeader("Content-Disposition", "attachment; filename=\"maroof.png\"")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new okhttp3.Callback(){
#Override
public void onFailure(Call call, IOException e) {
Log.e("OkHttp1", "onFailure: "+e.toString());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
ResponseBody body = response.body();
if (body != null) {
txtTestPath.setText(body.string());
} else {
Log.e("OkHttp1", "onResponse: null");
}
}
});
imgTestImage.setImageURI(uriSelectedImage);
}
}
}
With PostMan the media is upload without any problem, and following is the code generated from PostMan.
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file","/C:/Users/Abdul/OneDrive - OkamKSA/Alahdal/Personal/Web/SS/maroof.png",
RequestBody.create(MediaType.parse("application/octet-stream"),
new File("/C:/Users/Abdul/OneDrive - OkamKSA/Alahdal/Personal/Web/SS/maroof.png")))
.build();
Request request = new Request.Builder()
.url("https://test.matjri.com/wp-json/wp/v2/media")
.method("POST", body)
.addHeader("Authorization", "Bearer mytoken")
.addHeader("Cookie", "wp-wpml_current_admin_language_d41d8cd98f00b204e9800998ecf8427e=ar; _mcnc=1")
.build();
Response response = client.newCall(request).execute();
First of all, it is not the fault of AndroidNetworking, it is the permission denied, which I figured out after testing Retrofit, Retrofit throws the error for the permission denied which led me to fix the problem.
I checked above code after fixing the permission and it works very well.
Thank you
PS. There is no need for all the headers, token & Content-Disposition is enough.
Related
Here is how I get the image from photo library:
private void presentPhotoSelector() {
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, 0);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0 && resultCode == Activity.RESULT_OK && data != null) {
mSelectedPhotoUri = data.getData();
try {
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), mSelectedPhotoUri);
photoCircleImageView.setImageBitmap(bitmap);
photoCircleImageView.setVisibility(View.VISIBLE);
selectPhotoButton.setVisibility(View.INVISIBLE);
uploadImageToServer(mSelectedPhotoUri);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Here is how I try to upload it:
public class JSONResponse {
boolean userUploadedProfileImage;
User user;
}
private void uploadImageToServer(Uri selectedPhotoUri) {
if (selectedPhotoUri == null) {
Log.d(TAG, "uploadImageToServer: selectedPhotoUri is null");
return;
}
if (!AuthService.getInstance(mContext).isLoggedIn()) {
Log.d(TAG, "uploadImageToServer: User not logged in");
return;
}
showLoading("Laster opp bilde...", "Vennligst vent mens prosess foregÄr");
File file = new File(selectedPhotoUri.getPath());
final MediaType MEDIA_TYPE_JPG = MediaType.parse("image/jpeg");
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", "image.jpg",
RequestBody.create(MEDIA_TYPE_JPG, file))
.build();
Request request = new Request.Builder()
.header("Authorization", "Bearer " + AuthService.getInstance(mContext).getToken())
.url(Config.URL + "/api/user/upload-profile-image")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, final IOException e) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
hideLoading();
}
});
Log.d(TAG, "onFailure: response failed: " + e.getLocalizedMessage());
}
#Override
public void onResponse(Call call, Response response) throws IOException {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
hideLoading();
}
});
String responseBodyString = response.body().string();
Log.d(TAG, "onResponse: responseBodyString: " + responseBodyString);
Gson gson = new Gson();
SettingsFragment.JSONResponse jsonResponse = gson.fromJson(responseBodyString, SettingsFragment.JSONResponse.class);
if (jsonResponse != null) {
UserService.getInstance(mContext).setMyUser(jsonResponse.user);
Log.d(TAG, "onResponse: jsonResponse.userUploadedProfileImage: " + jsonResponse.userUploadedProfileImage);
Log.d(TAG, "onResponse: jsonResponse.user: " + jsonResponse.user.toString());
}
}
});
}
This does not work, the loader never stops spinning and on server side I get this error: multipart: NextPart: client disconnected
However, if I change the code above from:
File file = new File(selectedPhotoUri.getPath());
to:
String file = selectedPhotoUri.getPath();
Then request is successful, however, when I try to open the image on a browser it says "the image cannot be displayed because it contains errors". When I look at the database I can see that it interpreted its mime type as: application/octet-stream, and not image/jpeg.
I am stuck and I don't know what to do.
I am now getting this error on console: onFailure: response failed: /-1/1/content:/media/external/images/media/69/ORIGINAL/NONE/656735600 (No such file or directory)
I am running this on a simulator, if that helps.
One way is:
You have to convert Bitmap to Base64(String) and send that base64 to server.
I'm using spring for a backend and retrofit for rest client.
I want to upload a file
backend code
#PostMapping("/upload")
public ResponseEntity<String> handleFileUpload(#RequestParam("file") MultipartFile file, Model model) {
String name = null;
try {
storageService.store(file);
model.addAttribute("message", "You successfully uploaded " + file.getOriginalFilename() + "!");
files.add(file.getOriginalFilename());
name = files.get(files.size()-1).toString();
System.err.println(name.toString());
} catch (Exception e) {
model.addAttribute("message", "FAIL to upload " + file.getOriginalFilename() + "!");
}
return new ResponseEntity<String>(file.getOriginalFilename() , HttpStatus.OK);
}
function store
public void store(MultipartFile file) {
try {
Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
} catch (Exception e) {
throw new RuntimeException("FAIL!");
}
}
android code to select and upload file
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Bitmap bitmap = ImagePicker.getImageFromResult(getActivity(), requestCode, resultCode, data);
if (bitmap != null) {
image.setImageBitmap(bitmap);
selection=data.getData();
String[] filepath={MediaStore.Images.Media.DATA};
Cursor cursor=getActivity().getContentResolver().query(selection,filepath,null,null,null);
cursor.moveToFirst();
int column=cursor.getColumnIndex(filepath[0]);
String path=cursor.getString(column);
File file =new File(path);
RequestBody requestfile = RequestBody.create(MediaType.parse("multipart/form-data"),file);
MultipartBody.Part body = MultipartBody.Part.createFormData("image" , file.getName() , requestfile);
upload(body);
}
upload function
public void upload(MultipartBody.Part path){
Call<ResponseBody> callUploader = iBackEndService.uploadAttachment(path);
callUploader.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.d(TAG,"UPLODER REUSSI" +" "+response.message());
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable throwable) {
Log.e(TAG,throwable.getMessage());
}
});
}
Retrofit mapping (I'm using Retrofit 2.1.0)
#Multipart
#POST("upload")
Call<ResponseBody> uploadAttachment(#Part MultipartBody.Part filePart);
my upload function jump to onResponse but the file was not upload
I have implemented a retrofit client side implementation of uploading an image to a server using #MultipartBody but am unable to handle the upload on the server side:
This is my client side implementation (just to make sure I'm doing it right):
/**
* Activity
*/
#OnClick(R.id.change_profile_image_button)
public void addProfileImage() {
Intent pickIntent = new Intent();
pickIntent.setType("image/*");
pickIntent.setAction(Intent.ACTION_GET_CONTENT);
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String pickTitle = "Take or select a photo";
Intent chooserIntent = Intent.createChooser(pickIntent, pickTitle);
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { takePhotoIntent });
startActivityForResult(chooserIntent, REQUEST_CODE_PICTURE);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (data.getData() == null) {
Toast.makeText(getActivity(),
"Image file could not be uploaded",
Toast.LENGTH_SHORT).show();
return;
}
mProfileImageFile = getFileFromUri(data.getData());
mProfilePresenter.uploadProfileImage(mProfileImageFile);
}
}
private File getFileFromUri(Uri fileUri) {
if (fileUri != null) {
String filePath = fileUri.getPath();
if (filePath != null) {
return new File(filePath);
}
}
return null;
}
/**
* UserRepository
*/
#Override
public void uploadProfileImage(File file) {
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");
Call<ResponseBody> req = userServiceApi.uploadProfileImage(body, name);
req.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(#NonNull Call<ResponseBody> call,
#NonNull Response<ResponseBody> response) {
// Do Something
if (response.isSuccessful()) {
//String location = response.body();
//eventBus.post(new SuccessUploadProfileImageEvent(location));
Log.d(TAG, "Successfully uploaded image");
} else {
eventBus.post(new FailUploadProfileImageEvent());
}
}
#Override
public void onFailure(#NonNull Call<ResponseBody> call, #NonNull Throwable t) {
t.printStackTrace();
}
});
}
/**
* UserService
*/
#Multipart
#POST("users/upload-profile-image/")
Call<ResponseBody> uploadProfileImage(#Part MultipartBody.Part image,
#Part("name") RequestBody name);
On the server side I have tried to implement this view but it doesn't work:
class UserProfileUploadImageView(RetrieveModelMixin, UpdateModelMixin, generics.GenericAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAuthenticated,)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
#detail_route(methods=['POST'], permission_classes=[IsAuthenticated])
#parser_classes((FormParser, MultiPartParser,))
def image(self, request, *args, **kwargs):
if 'upload' in request.data:
user_profile = self.get_object()
user_profile.image.delete()
upload = request.data['upload']
user_profile.image.save(upload.name, upload)
return Response(status=HTTP_201_CREATED, body={'url': user_profile.image.url})
else:
return Response(status=HTTP_400_BAD_REQUEST)
And in the User model:
profile_image = models.ImageField(blank=True, null=True, upload_to="profile_image")
I have a function to request upload image with Retrofit like this
void uploadPhoto(File file) {
RequestBody photo = RequestBody.create(MediaType.parse("application/image"), file);
RequestBody body = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addFormDataPart("photo", file.getName(), photo)
.build();
fragment.showProgressDialog(fragment.loading);
fragment.getApi().uploadPhoto(PrefHelper.getString(PrefKey.TOKEN), body)
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(new Observer<GenericResponse>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
fragment.dismissProgressDialog();
Timber.e(e.getMessage());
}
#Override
public void onNext(GenericResponse response) {
fragment.dismissProgressDialog();
if (response.getCode() == 1) {
fragment.showSuccessDialog("Saving success", false);
userInfo();
}
}
});
}
and for the example, I have a button to upload image in my fragment
#OnClick(R.id.btnChangePicture)
void onChangePictureClicked() {
}
What code should i put in
OnChangePictureClicked
So i can choose an image from gallery and then I request it to API.
void uploadPhoto(File file)
Thanks
Transform your image to an array of bytes and then create an Object Dto like the example below and send it to the server through Retrofit.
#Data
public class SetProfileImageRequestDto {
#SerializedName("Token")
private String token;
#SerializedName("Stream")
private byte[] image;
}
Retrofit Api Service:
#POST("SetProfileImage/")
Observable<ResultResponseDto> setProfileImage(#Body SetProfileImageRequestDto profileImageRequestDto);
Hope it works.
Create a Uri object in Activity or fragment.
private Uri selectedImage;
After that, You will get gallery result in onActivityResult.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
selectedImage = data.getData();
}
}
Then in your onChangePictureClicked method.
#OnClick(R.id.btnChangePicture)
void onChangePictureClicked() {
if(selectedImage !=null){
uploadPhoto(new File(selectedImage.getPath()));
}
}
You can use multipart with retrofit please look this example of image upload using retrofit, its best for you.
its working for me.
//Create Upload Server Client
ApiService service = RetroClient.getApiService();
//File creating from selected URL
File file = new File(imagePath);
// create RequestBody instance from file
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body =
MultipartBody.Part.createFormData("uploaded_file", file.getName(), requestFile);
Call<Result> resultCall = service.uploadImage(body);
resultCall.enqueue(new Callback<Result>() {
#Override
public void onResponse(Call<Result> call, Response<Result> response) {
progressDialog.dismiss();
// Response Success or Fail
if (response.isSuccessful()) {
if (response.body().getResult().equals("success"))
Snackbar.make(parentView, R.string.string_upload_success, Snackbar.LENGTH_LONG).show();
else
Snackbar.make(parentView, R.string.string_upload_fail, Snackbar.LENGTH_LONG).show();
} else {
Snackbar.make(parentView, R.string.string_upload_fail, Snackbar.LENGTH_LONG).show();
}
/**
* Update Views
*/
imagePath = "";
textView.setVisibility(View.VISIBLE);
imageView.setVisibility(View.INVISIBLE);
}
#Override
public void onFailure(Call<Result> call, Throwable t) {
progressDialog.dismiss();
}
});
http://www.pratikbutani.com/2016/06/android-upload-image-file-using-retrofit-2-0/
I have this class:
public class FacebookShare extends Activity implements DialogListener {
Facebook facebook = new Facebook("199622693386109");
Bitmap bitmap;
byte [] data;
#Override
public void onCreate(Bundle savedInstanceState)
{
Bundle parameters = new Bundle();
parameters.putString("message", "Test Photo");
parameters.putByteArray("picture", data);
facebook.dialog(this, "stream.publish", parameters, this);
facebook.authorize(this, new DialogListener()
{
public void onComplete(Bundle values) {}
public void onFacebookError(FacebookError error) {}
public void onError(DialogError e) {}
public void onCancel() {}
});
}
}
but if I run this code, my app crashes. Please help.
parameters.putByteArray("picture", data);
data is your byte array of image....
and follow this link i did answer in this question....
we can upload photos using Facebook graph API with Multipart.
I am using retrofit library for network call
public interface ApiInterface {
#Multipart
#POST("/{id}/photos")
Call<UserModelResponse> uploadPhoto(#Part MultipartBody.Part image, #Path("id")String pageId, #Query("access_token") String token);
}
can upload multiple images
public class ApiCall {
private ApiInterface apiService;
private Context context;
public ApiCall(Context context) {
this.context = context;
}
public ApiInterface getRetroFitService() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Gson gson = new GsonBuilder().create();
Retrofit builder = new Retrofit.Builder()
.baseUrl("https://graph.facebook.com")
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
apiService = builder.create(ApiInterface.class);
return apiService;
}
public void uploadImageToFBPage(String pageId, ArrayList<Parcelable> path) throws IOException {
for (Parcelable parcelable : path) {
MultipartBody.Part body = prepareFilePart("source", (Uri) parcelable);
SharedPreferences sharedPreferences = context.getSharedPreferences(PREFERENCE, Context.MODE_PRIVATE);
String token = sharedPreferences.getString("token", "");
Call<UserModelResponse> call = apiService.uploadPhoto(body, pageId, token);
call.enqueue(new Callback<UserModelResponse>() {
#Override
public void onResponse
(Call<UserModelResponse> call, Response<UserModelResponse> response) {
if (response.errorBody() == null) {
Toast.makeText(context, "Image upload Success", Toast.LENGTH_SHORT).show();
} else {
onFailure(call, new Exception());
}
}
#Override
public void onFailure(Call<UserModelResponse> call, Throwable t) {
Toast.makeText(context, "Image upload Fail", Toast.LENGTH_SHORT).show();
}
});
}
}
#NonNull
private MultipartBody.Part prepareFilePart(String partName, Uri fileUri) {
// https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
// use the FileUtils to get the actual file by uri
File file = FileUtils.getFile(context, fileUri);
// create RequestBody instance from file
RequestBody requestFile = RequestBody.create(MediaType.parse(context.getContentResolver().getType(fileUri)), file);
// MultipartBody.Part is used to send also the actual file name
return MultipartBody.Part.createFormData(partName, file.getName(), requestFile);
}
}