We have some code posting an image and some other data as part of a Multipart in a POST request. In Android is working just fine, but I can't seem to make it work on iOS, where I keep getting a 500 Internal Server Error. The working Android code looks like
String uploadURL = "http://someServer.com/upload";
String imageToUploadPath = "imgFilePath";// path de la imagen a subir
String userId = "123";
String token = "abcd";
HttpClient httpClient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(uploadURL);
File f = new File(imageToUploadPath);
FileBody fileBody = new FileBody(f);
MultipartEntity reqEntity = new MultipartEntity();
Charset chars = Charset.forName("ISO-8859-1");
reqEntity.addPart("id", new StringBody(userId, chars));
reqEntity.addPart("token", new StringBody(token, chars));
reqEntity.addPart("image", fileBody);
httppost.setEntity(reqEntity);
HttpResponse response = httpClient.execute(httppost);
My iOS attempt using AFNetworking is as follows
uploadURLStr = #"http://someServer.com/upload";
NSString *token = #"abcd";
NSString *userID = #"123";
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSMutableSet *supportedContentTypes = [manager.responseSerializer.acceptableContentTypes mutableCopy];
supportedContentTypes addObject:#"text/html"];
manager.responseSerializer.acceptableContentTypes = supportedContentTypes;
NSURLSessionTask *task = [manager POST:uploadURLStr
parameters:nil
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSDictionary *tokenHeaders = #{#"Content-Disposition": #"form-data",
#"name": #"token",
#"Content-Type": #"text/plain",
#"charset": #"ISO-8859-1",
#"Content-Transfer-Encoding": #"8bit"
};
[formData appendPartWithHeaders:tokenHeaders body:[token dataUsingEncoding:NSISOLatin1StringEncoding]];
NSMutableDictionary *userIDHeaders = [tokenHeaders mutableCopy];
[userIDHeaders setObject:#"id" forKey:#"name"];
[formData appendPartWithHeaders:[userIDHeaders copy] body:[userID dataUsingEncoding:NSISOLatin1StringEncoding]];
NSDictionary *imgHeaders = #{#"Content-Disposition": #"form-data",
#"name": #"image",
#"filename": fileName,
#"Content-Type": #"application/octet-stream",
#"Content-Transfer-Encoding": #"binary"
};
[formData appendPartWithHeaders:imgHeaders
body:[imgData base64EncodedDataWithOptions:0]];
}
progress:^(NSProgress *uploadProgress) {
NSLog(#"progress: %.2f", uploadProgress.fractionCompleted);
}
success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"responseObject = %#", responseObject);
} failure:^(NSURLSessionTask *task, NSError *error) {
[self showUploadError];
NSLog(#"error = %#", error);
}];
Headers for each part we managed to log it from the Android app so we replicated it -for instance, I was sending the image with a Content-Type of image/jpeg and Android sends it as application/octet-stream- I assume that the image data is not being encoded as in Android. I have tried with base64 encoding as it's in the code now -tried different options other than 0-, just leaving the NSData returned by UIImageJPEG representation but I can't hit the nail. Any help is appreciated.
Related
I have read lots of post to achieve the task like to upload image along with parameters using multipartentity and josn in android, but my problem is when i was trying to upload image and parameter without converting string to JSONobject then image has uploaded without an error but when i was trying to add response string to jsonobject then error occur in the logcat like ):
error: Value`<form of type java.lang.String cannot be converted to JSONObject.
Any one please help to resolve this issue? I want to send an image and JsonObject to an PHP Server with MultipartEntity. I am working on an app that allows the user upload an image by using HttpPost method. I use MultipartEntity and therefore I added the libraries apache-mime4j-0.6.1.jar, httpclient-4.3.1.jar, httpcore-4.3.1.jar and httpmime-4.2.1.jar into my app.
Here is my Code:
public JSONObject doFileUpload(String _fname, String _lname, String _email,
String _password, String _country, String _countrycode,
String _phone) {
File file1 = new File(selectedPath);
String urlString = "http://capstonehostingservices.com/fetch_new/app/index.php/fetch/register";
try {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(urlString);
FileBody bin1 = new FileBody(file1);
MultipartEntity reqEntity = new MultipartEntity();
reqEntity.addPart("photo", bin1);
reqEntity.addPart("first_name", new StringBody(_fname));
reqEntity.addPart("last_name", new StringBody(_lname));
reqEntity.addPart("email", new StringBody(_email));
reqEntity.addPart("password", new StringBody(_password));
reqEntity.addPart("country", new StringBody(_country));
reqEntity.addPart("country_code", new StringBody(_countrycode));
reqEntity.addPart("phone", new StringBody(_phone));
post.setEntity(reqEntity);
HttpResponse response = client.execute(post);
resEntity = response.getEntity();
String response_str = EntityUtils.toString(resEntity);
json = new JSONObject(response_str);
} catch (Exception ex) {
Log.e("Debug", "error: " + ex.getMessage(), ex);
}
return json;
}
In above code i was trying to convert response string to jsonobject, how to i achieve this?
I used selectedpath parameter as to get image path from gallary, I want to send an image and a JsonObject to an PHP Server with MultipartEntity. I am working on an app that allows the user upload an image by using HttpPost method. I use MultipartEntity and therefore I added the libraries apache-mime4j-0.6.1.jar, httpclient-4.3.1.jar, httpcore-4.3.1.jar and httpmime-4.2.1.jar into my app.
This may not be the best answer but it is a very good example to get started.
Use the following function to send file to server:
public static void postFile(String fileName) throws Exception {//fileName is path+filename of picture
String url_upload_image = "http://url-to-api/upload_photo.php";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url_upload_image);
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder
.create();
multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntity.addPart("file", new FileBody(new File(fileName)));
post.addHeader("id", id);//id is anything as you may need
post.setEntity(multipartEntity.build());
HttpResponse response = client.execute(post);
HttpEntity entity = response.getEntity();
entity.consumeContent();
client.getConnectionManager().shutdown();
}
PHP file that is at http://url-to-api/upload_photo.php
<?php
$name = $_POST['id'];
$file_path = "images/";
$file_path = $file_path . basename( $_FILES['file']['name']);
if(move_uploaded_file($_FILES['file']['tmp_name'], $file_path)) {
echo "success";
echo $name;
} else{
echo "fail";
}
?>
And make sure that your directory or folder in server is Executable, Writable and Readable. I had this as the major problem. This is called 777 permission.. Believe me, this is as important as other things to consider.
I am sending a HTTP POST request from android to a server using the script below
URI website = new URI("http://venkygcm.appspot.com");
HttpClient client = new DefaultHttpClient();
HttpPost request = new HttpPost(website);
request.setHeader("Content-Type", "application/json");
String currentDateTimeString = DateFormat.getDateTimeInstance().format(new Date());
JSONObject obj = new JSONObject();
obj.put("reg_id","Registration ID sent to the server");
obj.put("datetime",currentDateTimeString);
StringEntity se = new StringEntity(obj.toString());
request.setEntity(se);
HttpResponse response = client.execute(request);
String out = EntityUtils.toString(response.getEntity());
As I have sent a JSON Object, I must receive a JSON Object in the server. Instead I get a string containing the data of the body. The server is made in Python Google App Engine.
import webapp2
class MainPage(webapp2.RequestHandler):
def post(self):
self.response.out.write(" This is a POST Request \n")
req = self.request
a = req.get('body')
self.response.out.write(type(a))
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
I tried what AK09 suggested but i still get a string kind of object. What should be my next step?
import webapp2
import json
class MainPage(webapp2.RequestHandler):
def post(self):
self.response.out.write("This is a POST Request \n")
req = self.request
a = req.get('body')
b = json.dumps(a)
self.response.out.write(type(a))
self.response.out.write(type(b))
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
Finally this code worked
import webapp2
import json
class MainPage(webapp2.RequestHandler):
def post(self):
self.response.out.write("This is a POST Request \n")
req = self.request
a = req.body
b = json.loads(a)
self.response.out.write(b)
self.response.out.write(b['reg_id'])
self.response.out.write(b['datetime'])
self.response.out.write(type(b))
app = webapp2.WSGIApplication([('/', MainPage)], debug=True)
b comes out to be of the type List as is required.
I use this code that i found in some page but I only can upload images from my android application to the server and is working, but when i upload a video(.mp4) its saved as "file" like unknown.
public void upload() throws Exception {
//Url of the server
String url = "";
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
MultipartEntity mpEntity = new MultipartEntity();
//Path of the file to be uploaded
String filepath = "";
File file = new File(filepath);
ContentBody cbFile = new FileBody(file);
//Add the data to the multipart entity
mpEntity.addPart("image", cbFile);
mpEntity.addPart("name", new StringBody("Test", Charset.forName("UTF-8")));
mpEntity.addPart("data", new StringBody("This is test report", Charset.forName("UTF-8")));
post.setEntity(mpEntity);
//Execute the post request
HttpResponse response1 = client.execute(post);
//Get the response from the server
HttpEntity resEntity = response1.getEntity();
String Response=EntityUtils.toString(resEntity);
Log.d("Response:", Response);
//Generate the array from the response
JSONArray jsonarray = new JSONArray("["+Response+"]");
JSONObject jsonobject = jsonarray.getJSONObject(0);
//Get the result variables from response
String result = (jsonobject.getString("result"));
String msg = (jsonobject.getString("msg"));
//Close the connection
client.getConnectionManager().shutdown();
}
There is any way to make this work to upload videos too?
There is not issue with this code works fine for upload videos and images, the problem was i´m missing the file extension in the name, so when the video was uploaded it should be NAME.EXTENSION not only NAME.
NOTE:
For all the people who is trying to upload a large(2MB-10GB) image or video to the server the only solution i found was encode the file in chunks and upload each chunk to the server, from there you only have to encode the chunks again. NO SIZE LIMITATION :)!!!!
I want to send a string data, "" , in bytes format to server in android app. I uses the HttpClient but i think its not the right way, please help me how to do this?
in case of .net , i want similar code in java.
string boundary = Guid.NewGuid().ToString();
HttpWebRequest request = HttpWebRequest.Create(url)
as HttpWebRequest;
request.Method = "POST";
//request.ContentType = "application/json";
request.PreAuthenticate = true;
byte[] fulldata = Encoding.UTF8.GetBytes(data);
request.ContentLength = fulldata.Length;
using (Stream sw = request.GetRequestStream())
{
sw.Write(fulldata, 0, fulldata.Length);
}
First convert your string data to byte and by using ByteArrayEntity send data to server in byte format.
try like this
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.1.1/xxx");
HttpResponse response;
HttpParams hp = new BasicHttpParams();
//use ByteArrayEntity to send string data in byteformat
ByteArrayEntity byteEntity = new ByteArrayEntity(byte_data);
httppost.setEntity(byteEntity);
response = httpclient.execute(httppost);
I have a rest webservice that takes a POST metod with multipart message:
#Path("transferFile")
#POST
#Consumes(MediaType.MULTIPART_FORM_DATA)
#Produces(MediaType.APPLICATION_XML)
public String multipartTest(com.sun.jersey.multipart.MultiPart data) {
try {
// get first body part (index 0)
BodyPart bp = multiPart.getBodyParts().get(0);
etc..
Now I am trying to write a java client for that. I started with a simple jersey client:
view plaincopy to clipboardprint?
MultiPart multiPart = new MultiPart();
multiPart.bodyPart( new BodyPart(wavestream,MediaType.APPLICATION_OCTET_STREAM_TYPE));
Client c = Client.create();
WebResource r = c.resource("http://127.0.0.1:8080/webapp:);
response=r.path("transferFile").type(MediaType.MULTIPART_FORM_DATA).accept(MediaType.APPLICATION_XML).post(String.class, multiPart);
This works great - everything is ok. However I need this client working on Android and I have trouble with using jersey on that platform. So I used the normal way to send multipart message on android:
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter("http.socket.timeout", new Integer(90000)); // 90 second
HttpPost httpPost = new HttpPost("http://127.0.0.1:8080/webapp/transferFile");
httpPost.setHeader("Content-Type", MediaType.MULTIPART_FORM_DATA );
//tried with and without base64
byte [] encodedWavestream = Base64.encodeBytesToBytes(wavestream);
InputStream ins = new ByteArrayInputStream(encodedWavestream);
InputStreamBody body = new InputStreamBody(ins, "test" );
int send = ins.available();
MultipartEntity requestContent = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE );
requestContent.addPart("stream", body);
httpPost.setEntity(requestContent);
HttpResponse Response = client.execute(httpPost);
An this gives an annoying response from the server :
HTTP Status 400 - Bad Request
The request sent by the client was syntactically incorrect (Bad Request).
I check the server log files but there is nothing there. So I don't know what's the origin of this error. I have wrote a simple html page with a post formula and 'multipart/form-data' content-type and it also works! An auto-generated request from soapUI also works! Why my client does not work? Can anybody help?
There is bug in Jersey. See Chunked encoding problem.
This problem appears only for few clients (iOS, Android).
If you set the Content-Type to application/octet-stream, then the Jersey MessageWriter for the application/octet-stream will set the Content-Length and
not send as chunked transport method.
There is solution for Jersey Client:
ClientConfig config = new DefaultClientConfig();
config.getProperties().put(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 32 * 1024);
But it doesn't work for the iOS's or Android's client.
So I tested Apache File Upload. Threre was another bug: "Stream ended unexpectedly".
Only Oreilly upload can upload file correct for all clients.
This is my code:
public Object[] getParametersAndFiles(HttpServletRequest request) throws IOException {
log.debug("OreillyUpload");
Properties params = new Properties();
LinkedHashMap files = new LinkedHashMap();
File tempDirectory = new File(System.getProperty("java.io.tmpdir"));
MultipartParser mp = new MultipartParser(request, 1*1024*1024); // 10MB
Part part;
while ((part = mp.readNextPart()) != null) {
String name = part.getName();
if (part.isParam()) {
// it's a parameter part
ParamPart paramPart = (ParamPart) part;
String value = paramPart.getStringValue();
params.put(name, value);
log.debug("param; name=" + name + ", value=" + value);
}
else if (part.isFile()) {
// it's a file part
FilePart filePart = (FilePart) part;
String fileName = filePart.getFileName();
if (fileName != null) {
// the part actually contained a file
File file = new File(tempDirectory,fileName);
long size = filePart.writeTo(file);
files.put(name, file);
log.debug("file; name=" + name + "; filename=" + fileName +
", filePath=" + filePart.getFilePath() +
", content type=" + filePart.getContentType() +
", size=" + size);
}
else {
// the field did not contain a file
log.debug("file; name=" + name + "; EMPTY");
}
}
}
return new Object[] {params, files};
}
And this is Jersey Server code (warning all Jersey Upload anotations (like as "#FormDataParam") should be removed):
#POST
#Path("uploadMarkup")
#Produces(MediaType.APPLICATION_JSON)
// #Consumes(MediaType.MULTIPART_FORM_DATA)
//// public void uploadMarkup(
// public JSONWithPadding uploadMarkup(
// #FormDataParam("markupFile") InputStream markupFile,
// #FormDataParam("markupFile") FormDataContentDisposition details,
// #FormDataParam("slideNum") int slideNum) {
public JSONWithPadding uploadMarkup(#Context HttpServletRequest request) {
Object[] data = uploadService.getParametersAndFiles(request);
...
}