Reputation: 4567
Hi I'm primarily an Android developer and am pretty clueless about http protocols, you help would be much appreciated!
I am trying to make an api call to this: http://api.haikutest.com/developer/apidoc/assignments.html where I POST a file on the device.
They give a sample request of:
POST /api/assignments/3/submit
message[subject]=Subject+of+the+message&message[body]=Some+long+text&message[sent_at]=2013-07-05&message[draft]=0&message[assignment_id]=3&files[][file]=%23%3CFile%3A0x007ff59c9c1de8%3E&files[][filename]=test.pdf
And in the description state that the files param is:
Array of files with each element containing a hash of filename and base64 encoded file
This is the code that I'm trying right now (note: I'm using Robospice + Spring for Android):
File file = new File(Environment.getExternalStorageDirectory() +
"/DCIM/Camera/1357279228432.jpg");
Base64InputStream stream = new Base64InputStream(new FileInputStream(file), 0);
HttpHeaders headers = new HttpHeaders();
headers.add("x-haiku-auth", HaikuAPI.getAuthHeader());
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
parts.add("files[][file]", parts);
HttpEntity<Object> request = new HttpEntity<Object>(stream, headers);
UriComponentsBuilder builder = UriComponentsBuilder
.fromUriString(
"https://" + HaikuAPI.getDomain() + "/api/assignments")
.pathSegment(assignmentID + "", "submit")
.queryParam("message[subject]", "Assignment Completed")
.queryParam("message[body]", message)
.queryParam("message[assignment_id]", assignmentID)
.queryParam("files[][filename]", "test.jpg");
URI url = builder.build().toUri();
String response = getRestTemplate().postForObject(url, request, String.class);
return response;
But I get an error saying that it can't serialize the stream to JSON. Following the API documentation do I have to place the stream as a param? Also what is the correct way to implement this? I would love if I didn't have to put a file size limit on the user, hence the streams. Though I have gotten it to work with small files encoded in Base64 and placed directly as a param...
Any help is greatly appreciated! I will definitely not downvote comments or answers for small pointers.
Updated
Updated code, but still get another error message:
00:25:50.904 Thread-2066 An exception occurred during request network execution :Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [application/x-www-form-urlencoded]
Upvotes: 0
Views: 1929
Reputation: 14710
Looks like you're using Spring for Android
. Judging that error message it seems Spring forces the content type to be application/json
, while I believe you're trying to send application/x-www-form-urlencoded
. So set this Content-Type
header:
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
Spring will know then to match the proper MessageConverter
. More info on this here.
EDIT: Also, you're supposed to send the request data in POST data, not in request URI. Move that to a MultiValuesMap
. Have a look at the link I gave you how to post such data. A complete documentation on these can also be found here.
EDIT2 You need to set the MessageConverter
for your response as well. Something like:
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.APPLICATION_JSON);
headers.setAccept(acceptableMediaTypes);
EDIT3 If you need to send files, consider using Resource
, to be more specific InputStreamResource
. But there is a trick: you need to provide the file name and the file size, otherwise your request will crash. Something like:
Resource res = new InputStreamResource(context.getContentResolver().openInputStream(itemImage)) {
@Override
public String getFilename() throws IllegalStateException {
return fileInfo.getFileName();
}
@Override
public long contentLength() throws IOException {
return fileInfo.getFileSizeInBytes();
}
};
Upvotes: 1