In my application, I want to upload image to the server and for this, I used Retrofit2.
I write the below codes, but after upload the image shows me a server error!
This error is: Media field is empty, please fill this!
This error is from my server and says to me the media field is empty!
My API codes:
#Multipart
#POST("/media")
fun uploadImage(
#Header(AUTHORIZATION) auth: String, #Header(ACCEPT) accept: String, #Header(CONTENT_TYPE) contentType: String,
#PartMap map: LinkedHashMap<String, RequestBody>
): Single<Response<ResponseModelUploadImage>>
My Activity codes:
var requestBody: RequestBody
var body: MultipartBody.Part
val mapRequestBody = LinkedHashMap<String, RequestBody>()
Log.e("filePath",uploadNaturalImageFile.toString())
requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), uploadNaturalImageFile);
mapRequestBody.put("media\"; media=\"" + uploadNaturalImageFile.name, requestBody);
presenter.callUploadImage(userToken, APPLICATION_JSON, APPLICATION_JSON, mapRequestBody)
But when upload this image with Postman, everything is OK and doesn't have any problem!
Postman request image:
UPDATE : I see my log and show me name=media, but server again media is empty!
My logcat messages:
D/OkHttp: Content-Disposition: form-data; name="media"; filename="JPEG_20201108_1623315560915977415445829.jpg"
Why show me this error? how can I fix it?
in your RetrofitService.java
#Multipart
#POST("/app/uploadFile.do")
Call<JsonObject> uploadFile(#PartMap() LinkedHashMap<String, RequestBody> partMap, #Part List<MultipartBody.Part> names);
and in your activity,
public static void fileUpload (File file) {
Log.d(TAG, "file===" + file.getName());
RequestBody requestBody;
MultipartBody.Part body;
LinkedHashMap<String, RequestBody> mapRequestBody = new LinkedHashMap<String, RequestBody>();
List<MultipartBody.Part> arrBody = new ArrayList<>();
requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
mapRequestBody.put("file\"; filename=\"" + file.getName(), requestBody);
mapRequestBody.put("test", RequestBody.create(MediaType.parse("text/plain"), "gogogogogogogog"));
body = MultipartBody.Part.createFormData("fileName", file.getName(), requestBody);
arrBody.add(body);
Call<JsonObject> call = RetrofitImg.getInstance().getService().uploadFile(mapRequestBody, arrBody);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
if (response.body() != null) {
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
Log.e(TAG + "Err", t.getMessage());
}
});
}
UPDATA : I found other example
#POST("my/files/photo/")
Call<FileUploadResponse> uploadPhoto(#Header("Content-Type") String contentType,
#Header("Authorization") String auth,
#Body MultipartBody body);
and
ApiClient.ApiInterface client = ApiClient.getClient();
File file = new File(getPathFromUri(fileUri));
RequestBody fileBody = RequestBody.create(MediaType.parse(getContentResolver().getType(fileUri)), file);
MultipartBody body = new MultipartBody.Builder().addFormDataPart("file-type", "profile")
.addFormDataPart("photo", "image.png", fileBody)
.build();
client.uploadPhoto("multipart/form-data; boundary=" + body.boundary(),
PrefManager.getInstance().getToken(), body);
Related
I've tried different approach but still getting stream was reset: NO_ERROR response from onFailure() using Retrofit.
What is the correct way to implement this kind of setup?
This is what my APIService looks like:
#Multipart
#POST(CREATE_STUDENT_RECORD)
Call<CreateStudentResult> createStudentRecord(#Header(PARAM_TOKEN) String token, #Part("studentlist") RequestBody studentList,
#Part MultipartBody.Part image, #Part("type") RequestBody type);
And this is my API Call:
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), APIConstants.capturedImage);
MultipartBody.Part filePart = MultipartBody.Part.createFormData("image", APIConstants.capturedImage.getName(), requestBody);
RequestBody type = RequestBody.create(
MediaType.parse("text/plain"),
"Students");
String studentList = new Gson().toJson(APIConstants.studentRecord);
RequestBody students = RequestBody.create(
MediaType.parse("text/plain"),
studentList);
The image section isn't quite correct. You are sending a file of type "image/jpeg", so instead of:
RequestBody requestBody = RequestBody.create(
MediaType.parse("multipart/form-data"),
APIConstants.capturedImage
);
MultipartBody.Part filePart = MultipartBody.Part.createFormData(
"image",
APIConstants.capturedImage.getName(),
requestBody
);
You want:
RequestBody requestBody = RequestBody.create(
MediaType.parse("image/jpeg"),
APIConstants.capturedImage
);
MultipartBody.Part filePart = MultipartBody.Part.createFormData(
"image",
APIConstants.capturedImage.getName(),
requestBody);
I'm recreating a project that was originally designed for Native Android to use React Native. There is an endpoint that is responsible to send a image using Form Data. I tried to convert the OkHttp3's Form Data to Axios's Form Data and I'm getting an error from backend saying that the request fields doesn't match.
My Code so far:
- Native Android(original app):
public RequestResponse<Boolean> functionApi(#NonNull String id, String imageExtension, #NonNull byte[] imageData, #NonNull String anotherData) throws ServerErrorException, IOException, AuthenticationException {
String path = "route/" + id;
Pair<String, String> contentTypeHeader = new Pair<>("Content-Type", "multipart/form-data");
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("anotherData", anotherData)
.addFormDataPart("imageData", id + "." + imageExtension, RequestBody.create(MediaType.parse("image/png"), imageData))
.build();
Response response = MyHttpClient.execute(path, "POST", requestBody, contentTypeHeader);
String body = response.body().string();
RequestResponse<Boolean> r = responseBodyToObject(body, RequestResponse.class);
r.setBody(r.getStatus() != RequestResponse.ERROR);
return r;
}
React Native(new app) version:
export const functionApi = async(id,imageExtension,imageData,anotherData)=>{
try{
let formData = new FormData()
formData.append('anotherData',anotherData)
formData.append('imageData',`data:image/${imageExtension};base64,${imageData}`,`${id}.${imageExtension}`)
//imageData here i tried to use a base64's string
let res = await axios({
url:`${URL_SERVER}/route/${id}`,
method:'POST',
headers:{
'Content-Type':"multipart/form-data"
},
data:formData
})
return res['data']
}catch(err){
return getErrorMessage(err)
}
}
I got a solution that finally worked for me:
export const functionApi = async(id,imageExtension,imageData,anotherData)=>{
try{
let formData = new FormData()
formData.append('anotherData',anotherData)
formData.append('imageData',{
uri: imageData['uri'],
type: 'image/jpg',
name: `${id}.${imageExtension}`,
})
let res = await axios({
url:`${URL_SERVER}/route/${id}`,
method:'POST',
headers:{
'Content-Type':'multipart/form-data'
},
data:formData
})
return res['data']
}catch(err){
return getErrorMessage(err)
}
}
I have this node.js code in my server side app:
app.post('/upload',function (req,resp) {
console.log(req);
var email=req.headers['email']
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null,'uploads/')
},
filename: function (req, file, cb) {
cb(null,"asdsad"+".jpg")
}
})
var upload = multer({ storage: storage }).single('propic')
upload(req, resp, function (err) {
if (err) {
throw err
}
resp.setHeader('Content-Type', 'application/json');
resp.send({status:true})
})
})
I want to send a bitmap in client side (Android) to server.
I used the okhttp library and I want to create form-data.
How can I do that?
You must send File to your server instead of bitmap and must use POST method to handle the request to Server side.
and write this codes to send your file into the server:
public class UploadService {
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
public void uploadImage(File image, String imageName) throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file", imageName, RequestBody.create(MEDIA_TYPE_PNG, image))
.build();
Request request = new Request.Builder().url("http://localhost:8080/v1/upload")
.post(requestBody).build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
}
}
I want to make a request with two headers in an Android app, the first one has a parameter. I tried this:
#Headers("Content-Type: application/json")
#GET("/ebuzon/client/show")
Call<Client> showClient(#Header("Authorization") String token);
call = api.showClient(" Bearer " +MySharedUser.getInstance().getToken());
401 UNATHORIZED
Edited: this should work, see #Robert answer. My problem was also updating token
#GET("/ebuzon/client/show")
Call<Client> showClient(#Header("Authorization") String token,
#Header("Content-Type") String appJson);
call = api.showClient(" Bearer" +MySharedUser.getInstance().getToken(), "application/json");
401 UNATHORIZED
#Headers({"Authorization: Bearer {token}","Content-Type: application/json"})
#GET("/ebuzon/client/show")
Call<Client> showClient(#Path("token") String token);
IllegalArgumentException: URL "/ebuzon/client/show" does not contain "{token}". (parameter #1)
I am doing the same in angular like this and it's working
var obj = this.http.get("/ebuzon/client/show",
{headers: new HttpHeaders().set("Authorization", " Bearer "+ this.token).append("Content-Type","application/json")})
.map(res => {
console.log(res);
return res
})
.catch(err => {
console.log(err);
return err;
})
return obj;
Thanks for any help.
Maybe this will help you out..Maybe you need to add a header in your request..
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + token)
.build();
return chain.proceed(newRequest);
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(/** your url **/)
.addConverterFactory(GsonConverterFactory.create())
.build();
Method 1 or 2 should work.
I believe the problem might be on the way you construct the value.
(" Bearer" +MySharedUser.getInstance().getToken());
This will result in something like
" Bearer{SOME_TOKEN}"
When in reality, you most likely want it to be something like
"Bearer {SOME_TOKEN}"
I am new to typescript and trying to upload an image from my mobile SD card. I am getting the image path when browsing the image. And when I pass this along with the form data None is returning. It would be great if someone give a helping hand to figure out the issue.
I am using "nativescript-imagepicker" library for getting image from SD Card..
sendPicture(uri: string, modelContext: any){
let _formData = new FormData();
_formData.append("profile_image", uri);
let body = _formData;
updateAvatarService(this.userToken,body).subscribe(data => {
});
}
updateAvatarService(token,body): Observable<any> {
return this.httpClass.patchMethodWithToken(URL,token,body)
.map(response => {
return response;
})
}
patchMethodWithToken(url: string, token: string, data: Object ) {
let headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', "Token " + token);
headers.append('Content-Disposition', "form-data");
let options = new RequestOptions({ headers: headers });
if (this.checkNetworkConnection()) {
return this.http
.patch(url, JSON.stringify(data), options)
.map(response => {
return response.json();
})
.catch(this.handleErrors);
}
}
For multipart upload as form data I was using Nativescript-background-Http
Below is the sample implementation and it is working for me -
import { session, Session, Task } from "nativescript-background-http";
var session1 = session("image-upload");
uploadImage(fileUri, id) {
let imageName = this.extractImageName(fileUri);
let headers = new Headers();
headers.append("Authorization", Config.token);
headers.append("CenterId", Config.CenterId);
var options = new RequestOptions({ headers: headers });
var request = {
url: Config.putImage + id + "/upload",
method: "POST",
headers: {
"Authorization": Config.token,
"X-Center-Id": Config.XCenterId,
"Content-Type": "application/octet-stream",
"File-Name": imageName
},
description: "{ 'uploading': " + imageName + " }"
};
var params = [{ name: "image", filename: fileUri, mimeType: 'image/jpeg' }];
var task = session1.multipartUpload(params, request);
task.on("progress", logEvent);
task.on("error", logEvent);
task.on("complete", logEvent);
function logEvent(e) {
console.log(".........................")
console.log("currentBytes: " + e.currentBytes);
console.log(".........................")
console.log("totalBytes: " + e.totalBytes);
console.log(".........................")
}
return task;
}
//Extract file Name
extractImageName(fileUri) {
var pattern = /[^/]*$/;
var imageName = fileUri.match(pattern);
return imageName;
}