I would like upload any data (Username, Description,..) and a photo from my Android-App to my Server (PHP-Script).
By searching for this i found a solution: How to take a photo and send to HTTP POST request with Android?
By click on my send button, the upload-process starts and the php-script works but the $_POST -Vars are empty? Can anybody help me? My request-code:
[...]
case R.id.btnSend:
String strName = tName.getText().toString();
String strEmail = tEmail.getText().toString();
String strDatum = tDatum.getText().toString();
String strBeschreibung = tBeschreibung.getText().toString();
nvPairs = new ArrayList<NameValuePair>(2);
nvPairs.add(new BasicNameValuePair("sender", "AndoidApp"));
nvPairs.add(new BasicNameValuePair("name", strName));
nvPairs.add(new BasicNameValuePair("email", strEmail));
nvPairs.add(new BasicNameValuePair("datum", strDatum));
nvPairs.add(new BasicNameValuePair("beschreibung", strBeschreibung));
nvPairs.add(new BasicNameValuePair("bild", bmpUrl));
new UploadTask().execute();
}
[...]
private class UploadTask extends AsyncTask<Void, Void, List<String>> {
#Override
protected List<String> doInBackground(Void... params) {
String response = "";
try {
response = new MultipartServer().postData(new URL(postUrl), nvPairs);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
On the MultipartServer-Code i changed the line:
if ((avatarName = pair.getName()).equals("avatar")) {
avatarPath = pair.getValue();
}
to this:
if ((avatarName = pair.getName()).equals("bild")) {
avatarPath = pair.getValue();
}
And the Variables "bmpUrl" and "postUrl" are set correctly at an another line in my code.
Thanks for your help! I found an solution for the problem. The problem was at the Script from How to take a photo and send to HTTP POST request with Android?
I changed it to this:
public class MultipartServer {
private static final String TAG = "MultipartServer";
private static final String crlf = "\r\n";
private static final String twoHyphens = "--";
private static final String boundary = "AaB03x"; //*****
private String avatarName = null;
private String avatarPath = null;
public String postData(URL url, List<NameValuePair> nameValuePairs) throws IOException {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setReadTimeout(10000);
connection.setConnectTimeout(15000);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Cache-Control", "no-cache");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
FileInputStream inputStream;
OutputStream outputStream = connection.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
for (NameValuePair pair : nameValuePairs) {
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(twoHyphens + boundary + crlf);
dataOutputStream.writeBytes(
"Content-Disposition: form-data; name=\""
+ URLEncoder.encode(pair.getName(), "UTF-8")
+ "\";" + crlf);
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(URLEncoder.encode(pair.getValue(), "UTF-8"));
if (pair.getName().equals("bild")) {
avatarName = pair.getName();
avatarPath = pair.getValue();
}
}
// Write Avatar (if any)
if (avatarName != null && avatarPath != null) {
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(twoHyphens + boundary + crlf);
dataOutputStream
.writeBytes("Content-Disposition: form-data; name=\""
+ avatarName + "\";filename=\""
+ new File(avatarPath).getName() + "\";" + crlf);
dataOutputStream.writeBytes(crlf);
inputStream = new FileInputStream(avatarPath);
byte[] data = new byte[1024];
int read;
while ((read = inputStream.read(data)) != -1)
dataOutputStream.write(data, 0, read);
inputStream.close();
dataOutputStream.writeBytes(crlf);
dataOutputStream.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
}
dataOutputStream.flush();
dataOutputStream.close();
String responseMessage = connection.getResponseMessage();
Log.d(TAG, responseMessage);
InputStream in = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(in, "UTF-8"));
StringBuilder response = new StringBuilder();
char[] b = new char[512];
int read;
while ((read = bufferedReader.read(b)) != -1) {
response.append(b, 0, read);
}
connection.disconnect();
Log.d(TAG, response.toString());
return response.toString();
}
}
Related
Today I'm trying to upload and image to a server. I found that a lot of developers recommend the use of HttpURLConnection. The performance is very important for me, so I tried to optimize the code the most I know how to do it. The problem I faced is that the uploaded images are considerably larger than the original ones.
If anyone sees something that can be done better, it would be of great help
This is my class to upload a bitmap:
private class SubirImagen extends AsyncTask<Bitmap, Integer, APIResponse<String>> {
String token;
String boundary = "***" + System.currentTimeMillis() + "***";
String crlf = "\r\n";
String twoHyphens = "--";
public SubirImagen(String token) {
this.token = token;
}
#Override
protected void onPostExecute(APIResponse<String> stringAPIResponse) {
progressBar.setVisibility(View.INVISIBLE);
if (stringAPIResponse.getErrors().isEmpty()) {
new File(pathToFile.getPath()).delete();
imagenCambiada = false;
pathToFile = null;
controler.showToast(getContext(), stringAPIResponse.getData());
} else {
controler.showToast(getContext(), stringAPIResponse.getErrors().get(0).getErrorMsg());
}
super.onPostExecute(stringAPIResponse);
}
#Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(0);
super.onPreExecute();
}
#Override
protected void onProgressUpdate(Integer... values) {
progressBar.setProgress(values[0]);
}
#Override
protected APIResponse<String> doInBackground(Bitmap... bitmaps) {
ByteArrayOutputStream bao1 = new ByteArrayOutputStream();
bitmaps[0].compress(Bitmap.CompressFormat.JPEG, 100, bao1);
byte[] ba1 = bao1.toByteArray();
int size = (twoHyphens.length() * 3) + (boundary.length() * 2) + (crlf.length() * 5) +
("Content-Disposition: form-data; name=\"imagen\";filename=\"imagen\"".length()) +
ba1.length;
HttpURLConnection urlConnection = null;
try {
URL url = new URL("http://192.168.137.1:8080/BochoGameAPI/usuario/uploadFotoPerfil");
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", token);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setRequestProperty("Cache-Control", "no-cache");
urlConnection.setRequestProperty("ENCTYPE", "multipart/form-data");
urlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
urlConnection.setFixedLengthStreamingMode(size);
DataOutputStream request = new DataOutputStream(urlConnection.getOutputStream());
request.writeBytes(twoHyphens + boundary + crlf);
request.writeBytes("Content-Disposition: form-data; name=\"imagen\";filename=\"imagen\"" + crlf);
request.writeBytes(crlf);
request.flush();
int progress = 0;
int bytesRead;
byte buf[] = new byte[1024];
BufferedInputStream bufInput = new BufferedInputStream(new ByteArrayInputStream(ba1));
while ((bytesRead = bufInput.read(buf)) != -1) {
// write output
request.write(buf, 0, bytesRead);
request.flush();
progress += bytesRead;
// update progress bar
publishProgress((progress * 100) / size);
}
request.write(ba1);
request.writeBytes(crlf);
request.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
request.flush();
request.close();
int code = urlConnection.getResponseCode();
if (code != 200) {
throw new IOException("Invalid response from server: " + code);
}
BufferedReader rd = new BufferedReader(new InputStreamReader(
urlConnection.getInputStream()));
String line;
Gson gson = new Gson();
Type typeToken = new TypeToken<APIResponse<String>>() {
}.getType();
APIResponse<String> apiResponse = null;
while ((line = rd.readLine()) != null) {
apiResponse = gson.fromJson(line, typeToken);
}
rd.close();
return apiResponse;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
return null;
}
}
Original image, 1.57 mb:
Uploaded image, 4.19 mb:
I wanna send a file and some variables to server, to insert in a table in a android app using AsyncTask. here is my java code:
try {
URL url = new URL(upLoadServerUri);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
OutputStream outputStream = httpURLConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream,"UTF-8"));
String post_data= URLEncoder.encode("username" , "UTF-8")+"="+URLEncoder.encode(username,"UTF-8");
bufferedWriter.write(post_data);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.close();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "iso-8859-1"));
result="";
String line="";
while ((line=bufferedReader.readLine()) != null){
result += line;
}
bufferedReader.close();
inputStream.close();
httpURLConnection.disconnect();
}catch (MalformedURLException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
try {
FileInputStream fileInputStream = new FileInputStream(sourceFile);
URL url = new URL(upLoadServerUri);
// Open a HTTP connection to the URL
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true); // Allow Inputs
conn.setDoOutput(true); // Allow Outputs
conn.setUseCaches(false); // Don't use a Cached Copy
conn.setRequestMethod("POST");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("ENCTYPE",
"multipart/form-data");
conn.setRequestProperty("Content-Type",
"multipart/form-data;boundary=" + boundary);
conn.setRequestProperty("bill", sourceFileUri);
dos = new DataOutputStream(conn.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"bill\";filename=\""
+ sourceFileUri + "\"" + lineEnd);
dos.writeBytes(lineEnd);
// create a buffer of maximum size
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0,
bufferSize);
}
// send multipart form data necesssary after file
// data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// Responses from the server (code and message)
serverResponseCode = conn.getResponseCode();
String serverResponseMessage = conn
.getResponseMessage();
// close the streams //
fileInputStream.close();
dos.flush();
dos.close();
return result;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
And PHP code:
if (is_uploaded_file($_FILES['bill']['tmp_name'])) {
$uploads_dir = './sensorLog/$user_name';
$tmp_name = $_FILES['bill']['tmp_name'];
$pic_name = $_FILES['bill']['name'];
move_uploaded_file($tmp_name, $uploads_dir.$pic_name);
if($conn->query($mysql_qry) === TRUE) {
echo "upload and update successful";
}else { echo "Error" . $mysql_qry . "<br>" . $conn->error;}
}else{ echo "File not uploaded successfully."; }
I use two httpconnection object and I think this is the problem. How can I send variables and file simultaneously? this code upload the file to server, but the table isn't updated. it just add an empty row:(.
Use this class to send multipart requests:
class MultipartUtility {
public HttpURLConnection httpConn;
public OutputStream request;//if you wanna send anything out of ordinary use this;
private final String boundary = "*****";//alter this as you wish
private final String crlf = "\r\n";
private final String twoHyphens = "--";
public MultipartUtility(String requestURL)
throws IOException {
URL url = new URL(requestURL);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setUseCaches(false);
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
//alter this part if you wanna set any headers or something
httpConn.setRequestProperty("Connection", "Keep-Alive");
httpConn.setRequestProperty("Cache-Control", "no-cache");
httpConn.setRequestProperty(
"Content-Type", "multipart/form-data;boundary=" + this.boundary);
request = httpConn.getOutputStream();
}
//or add some other constructor to better fit your needs; like set cookies and stuff
public void addFormField(String name, String value)throws IOException {
request.write(( this.twoHyphens + this.boundary + this.crlf).getBytes());
request.write(("Content-Disposition: form-data; name=\"" + name + "\""+ this.crlf).getBytes());
request.write(this.crlf.getBytes());
request.write((value).getBytes());
request.write(this.crlf.getBytes());
request.flush();
}
public void addFilePart(String fieldName, File uploadFile)
throws IOException,Exception {
if(uploadFile.isDirectory())throw new Exception("for real? what do you expect to happen?");
request.write((this.twoHyphens + this.boundary + this.crlf).getBytes());
request.write(("Content-Disposition: form-data; name=\"" +
fieldName + "\";filename=\"" +
uploadFile.getName()+ "\"" + this.crlf).getBytes());
request.write(this.crlf.getBytes());
InputStream is=new FileInputStream(uploadFile);
byte[] bytes = new byte[1024];
int c=is.read(bytes);
while(c>0){
request.write(bytes,0,c);
c=is.read(bytes);
}
request.write(this.crlf.getBytes());
request.flush();
is.close();
}
public String finish() throws IOException {
String response ="";
request.write((this.twoHyphens + this.boundary +
this.twoHyphens + this.crlf).getBytes());
request.flush();
request.close();
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
InputStream responseStream = httpConn.getInputStream();
byte[] b=new byte[1024];
int c=responseStream.read(b);
while(c>0){
response=response+new String(b,0,c);
c=responseStream.read(b);
}
responseStream.close();
} else {
httpConn.disconnect();
throw new IOException("Server returned non-OK status: " + status);
}
httpConn.disconnect();
return response;
}
public InputStream finish_with_inputstream()throws Exception{
request.write((this.twoHyphens + this.boundary +
this.twoHyphens + this.crlf).getBytes());
request.flush();
request.close();
int status = httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
return httpConn.getInputStream();
} else {
throw new IOException("Server returned non-OK status: " + status);
}
}
}
example:
try{
MultipartUtility m=new MultipartUtility("https://mydomain");//now add you different data parts;
m.addFilePart("file_part",new File("some_file_location"));
m.addFormField("value_name","value");
//call either of the below methods based on what you need; do not call both!
String result=m.finish();//call this if the response is a small text
InputStream is=m.finish_with_inputstream(); //call this if the response is huge and not fitting in memory; don't forget to disconnect the connection afterwards;
} catch (IOException e) {
e.printStackTrace();
}
now you can handle all these data in one request on the php side:
$value=$_POST["value_name"];
$file_data=file_get_contents($_FILES["file_part"]["tmp_name"])
so for you situation it would be like below:
try{
MultipartUtility m=new MultipartUtility("https://mydomain");
m.addFilePart("bill",new File(sourceFile));
m.addFormField(URLEncoder.encode("username" , "UTF-8"),URLEncoder.encode(username,"UTF-8"));
String result=m.finish();
} catch (Exception e) {
e.printStackTrace();
}
I'm trying to access another server for uploading files with Java. I'm able to connect to the server but I'm unable to upload the file.
The server (Spring Boot application) accepts the file in this way.
#PostMapping(value = ("multipart-store"), headers = ("content-type=multipart/*"))
CustomResponse gridFs(#RequestPart("file") MultipartFile multipartFile) throws Exception {
return new CustomResponse(storageService.storeObject(multipartFile));
}
I had tried couple of ways to access the server.
My Java code to access the server is below.
1st way
try {
final File uploadFile2 = new File("/home/thrymr/Desktop/invoicesample.pdf");
final String requestURL = "http://localhost:8082/data/multipart-store";
final MultipartUtility multipart = new MultipartUtility(requestURL, charset);
multipart.addFilePart("file", uploadFile2);
final List<String> response = multipart.finish();
System.out.println("SERVER REPLIED:");
for (final String line : response) {
System.out.println(line);
}
} catch (final IOException ex) {
System.err.println(ex);
}
public class MultipartUtility {
private final String boundary;
private static final String LINE_FEED = "\r\n";
private final HttpURLConnection httpConn;
private final String charset;
private final OutputStream outputStream;
private final PrintWriter writer;
public MultipartUtility(final String requestURL, final String charset) throws IOException {
this.charset = charset;
this.boundary = "" + System.currentTimeMillis() + "";
final URL url = new URL(requestURL);
this.httpConn = (HttpURLConnection) url.openConnection();
this.httpConn.setUseCaches(false);
this.httpConn.setDoOutput(true); // indicates POST method
this.httpConn.setDoInput(true);
this.httpConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + this.boundary);
this.outputStream = this.httpConn.getOutputStream();
this.writer = new PrintWriter(new OutputStreamWriter(this.outputStream, charset), true);
}
public void addFilePart(final String fieldName, final File uploadFile) throws IOException {
final String fileName = uploadFile.getName();
this.writer.append("file : "+uploadFile);
this.writer.flush();
final FileInputStream inputStream = new FileInputStream(uploadFile);
final byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
this.outputStream.write(buffer, 0, bytesRead);
}
this.outputStream.flush();
inputStream.close();
this.writer.append(LINE_FEED);
this.writer.flush();
}
public List<String> finish() throws IOException {
final List<String> response = new ArrayList<String>();
this.writer.append(LINE_FEED).flush();
this.writer.append("--" + this.boundary + "--").append(LINE_FEED);
this.writer.close();
final int status = this.httpConn.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
final BufferedReader reader = new BufferedReader(new InputStreamReader(this.httpConn.getInputStream()));
String line = null;
while ((line = reader.readLine()) != null) {
response.add(line);
}
reader.close();
this.httpConn.disconnect();
} else {
throw new IOException("Server returned non-OK status: " + status);
}
return response;
}
}
2nd way
final File file = new File("/home/thrymr/Desktop/invoicesample.pdf");
final HttpPost post = new HttpPost("http://localhost:8082/data/multipart-store");
final FileBody fileBody = new FileBody(file, ContentType.MULTIPART_FORM_DATA);
final MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addPart("file", fileBody);
final HttpEntity entity = builder.build();
post.setHeader("Content-Type", "multipart/form-data; boundary=gv");
final CloseableHttpClient client = HttpClients.createDefault();
post.setEntity(entity);
final HttpResponse response = client.execute(post);
System.out.println(response);
In the above addFilePart() method, by replacing this.writer.append("file : "+uploadFile); with below lines of code, i'm able to solve the issue.
this.writer.append("--" + this.boundary).append(LINE_FEED);
this.writer.append("Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"")
.append(LINE_FEED);
this.writer.append("Content-Type: " + URLConnection.guessContentTypeFromName(fileName)).append(LINE_FEED);
this.writer.append(LINE_FEED);
I am new to PHP. I am building an android project which needs to upload images to my server. The problem i am having is that when I send just a key and a value (no file) to the server, it works perfectly fine. However, as soon as I try to send a file, the superglobals $_POST and $_FILES in php are empty! The file sent is very small, so its not go to do with the file_max_upload_size. The file is not corrupted. I think it is something to do with the encoding of of the InputStream sent by the app on the android emulator. My code is below:
Java code in the app that sends the image along with a key-value pair:
public Future<JSONObject> asyncSendPOSTRequest(String URL, Map<String, String> params, Map<String, Pair<String,InputStream>> files) throws InterruptedException, ExecutionException, JSONException, UnsupportedEncodingException {
HttpPost request = new HttpPost(URL);
MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
if(params!=null) {
for(String key : params.keySet()) {
multipartEntity.addTextBody(key, params.get(key), ContentType.TEXT_PLAIN);
}
}
if(files!=null) {
for(String key : files.keySet()) {
multipartEntity.addPart(key, new InputStreamBody(files.get(key).second,ContentType.MULTIPART_FORM_DATA, files.get(key).first));
}
}
request.setEntity(multipartEntity.build());
Future<JSONObject> future = threadPool.submit(new executeRequest(request));
return future;
}
//Thread to communicate with server.
private class executeRequest implements Callable<JSONObject> {
HttpRequestBase request;
public executeRequest(HttpRequestBase request) {
this.request = request;
}
#Override
public JSONObject call() throws Exception {
HttpResponse httpResponse = httpClient.execute(request);
BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
StringBuilder stringReply = new StringBuilder();
String replyLine;
while ((replyLine = reader.readLine()) != null) {
stringReply.append(replyLine);
}
return new JSONObject(stringReply.toString());
}
}
The code on the server:
#!/usr/bin/php
<?php
$uploads_dir = __DIR__ . '/uploads';
$status = -1;
if ($_FILES["picture"]["error"] == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["picture"]["tmp_name"];
$name = $_FILES["picture"]["name"];
$status = move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
$response["status"] = $status;
$response["user_id"] = $_POST["user_id"];
$response["name"] = $name;
$response["extension"] = end (explode(".", $name));
echo json_encode($response);
?>
The possible problem that you set wrong datatype
enctype="multipart/form-data"
public class Helpher extends AsyncTask<String, Void, String> {
Context context;
JSONObject json;
ProgressDialog dialog;
int serverResponseCode = 0;
DataOutputStream dos = null;
FileInputStream fis = null;
BufferedReader br = null;
public Helpher(Context context) {
this.context = context;
}
protected void onPreExecute() {
dialog = ProgressDialog.show(Main2Activity.this, "ProgressDialog", "Wait!");
}
#Override
protected String doInBackground(String... arg0) {
try {
File f = new File(arg0[0]);
URL url = new URL("http://localhost:8888/imageupload.php");
int bytesRead;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
String contentDisposition = "Content-Disposition: form-data; name=\"keyValueForFile\"; filename=\""
+ f.getName() + "\"";
String contentType = "Content-Type: application/octet-stream";
dos = new DataOutputStream(conn.getOutputStream());
fis = new FileInputStream(f);
dos.writeBytes(SPACER + BOUNDARY + NEW_LINE);
dos.writeBytes("Content-Disposition: form-data; name=\"parameterKey\""
+ NEW_LINE);
dos.writeBytes(NEW_LINE);
dos.writeBytes("parameterValue" + NEW_LINE);
dos.writeBytes(SPACER + BOUNDARY + NEW_LINE);
dos.writeBytes(contentDisposition + NEW_LINE);
dos.writeBytes(contentType + NEW_LINE);
dos.writeBytes(NEW_LINE);
byte[] buffer = new byte[MAX_BUFFER_SIZE];
while ((bytesRead = fis.read(buffer)) != -1) {
dos.write(buffer, 0, bytesRead);
}
dos.writeBytes(NEW_LINE);
dos.writeBytes(SPACER + BOUNDARY + SPACER);
dos.flush();
int responseCode = conn.getResponseCode();
if (responseCode != 200) {
Log.w(TAG,
responseCode + " Error: " + conn.getResponseMessage());
return null;
}
br = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
Log.d(TAG, "Sucessfully uploaded " + f.getName());
} catch (MalformedURLException e) {
} catch (IOException e) {
} finally {
try {
dos.close();
if (fis != null)
fis.close();
if (br != null)
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return String.valueOf(serverResponseCode);
}
#Override
protected void onPostExecute(String result) {
dialog.dismiss();
}
}
This is the AsyncTask "Helpher" class used for upload image from Android. To call this class use like syntax below.
new Main2Activity.Helpher(this).execute(fileUri.getPath(),parameterValue);
Here fileUri.getPath() local image location.If you want to see the server response value is avilable in " StringBuilder sb" you can print sb value
I am trying to post a JSON representation of my object and an optional image to my Spring backend. However, I am having major trouble posting a request with an image. I have managed to post the first part to the server; the JSON object. However when I try to add a second part which is an image captured by the user nothing happens. I don't see any stacktraces.
What am I doing wrong and how do I post an image along the request. This is what I have...
String boundary = UUID.randomUUID().toString();
String twoHyphens = "--";
String attachmentName = "data";
String crlf = "\r\n";
try {
URI uri = new URI("http://myappserver.com/app");
HttpURLConnection urlConnection = (HttpURLConnection) uri.toURL().openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Connection", "Keep-Alive");
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream dos = new DataOutputStream(urlConnection.getOutputStream());
InputStream inputStream = context.getContentResolver().openInputStream(question.getUri());
// FIRST PART; A JSON object
dos.writeBytes(twoHyphens + boundary);
dos.writeBytes(crlf);
dos.writeBytes("Content-Type: application/json");
dos.writeBytes(crlf);
dos.writeBytes("Content-Disposition: form-data; name=\"data\"");
dos.writeBytes(crlf);
dos.writeBytes(crlf);
dos.writeBytes(jsonEntity);
dos.writeBytes(crlf);
// SECOND PART; A image..
dos.writeBytes(twoHyphens + boundary);
dos.writeBytes(crlf);
dos.writeBytes("Content-Type: image/jpg");
dos.writeBytes(crlf);
dos.writeBytes("Content-Disposition: form-data; name=\"image\"");
dos.writeBytes(crlf);
dos.writeBytes(crlf);
// Something must be done here. I guess I must encode it to Base64 here.
// How can I avoid loading the whole image at once so I don't get out of memory errors.
dos.writeBytes(crlf);
dos.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
dos.close();
} catch (Exception e) {
}
The code illustrates how to send a file (here it is pdf). Go through it, it will be helpful for you to debug your code.
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
FileInputStream fileInputStream = new FileInputStream(file);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"attachment_0\";filename=\"" + file.getName() + "\"" + lineEnd);
dos.writeBytes("Content-Type: text/pdf" + lineEnd);
dos.writeBytes("Content-Length: " + file.length() + lineEnd);
dos.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
fileInputStream.close();
}
//for sending a parameter, see below, key is the key of the webservice parameter.
dos.writeBytes("Content-Disposition: form-data; name=\""+key+"\"" + lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(requestData.get(key).toString() + lineEnd);
Below is my implementation of a MULTIPART form data upload using HttpURLConnection class. This class employs a Dynamic usage so that multiple request can be invoked at a time with different sets of data.
NB: I'm breaking the json part into individual text forms inorder to maintain consistency with my server. You may modify it to match your servers requirement.
public class WebConnector {
String boundary = "-------------" + System.currentTimeMillis();
private static final String LINE_FEED = "\r\n";
private static final String TWO_HYPHENS = "--";
private StringBuilder url;
private String protocol;
private HashMap<String, String> params;
private JSONObject postData;
private List<String> fileList;
private int count = 0;
private DataOutputStream dos;
public WebConnector(StringBuilder url, String protocol,
HashMap<String, String> params, JSONObject postData) {
super();
this.url = url;
this.protocol = protocol;
this.params = params;
this.postData = postData;
createServiceUrl();
}
public WebConnector(StringBuilder url, String protocol,
HashMap<String, String> params, JSONObject postData, List<String> fileList) {
super();
this.url = url;
this.protocol = protocol;
this.params = params;
this.postData = postData;
this.fileList = fileList;
createServiceUrl();
}
public String connectToMULTIPART_POST_service(String postName) {
System.out.println(">>>>>>>>>url : " + url);
StringBuilder stringBuilder = new StringBuilder();
String strResponse = "";
InputStream inputStream = null;
HttpURLConnection urlConnection = null;
try {
urlConnection = (HttpURLConnection) new URL(url.toString()).openConnection();
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestProperty("Connection", "close");
urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 ( compatible ) ");
urlConnection.setRequestProperty("Authorization", "Bearer " + Config.getConfigInstance().getAccessToken());
urlConnection.setRequestProperty("Content-type", "multipart/form-data; boundary=" + boundary);
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setUseCaches(false);
urlConnection.setChunkedStreamingMode(1024);
urlConnection.setRequestMethod("POST");
dos = new DataOutputStream(urlConnection.getOutputStream());
Iterator<String> keys = postData.keys();
while (keys.hasNext()) {
try {
String id = String.valueOf(keys.next());
addFormField(id, "" + postData.get(id));
System.out.println(id + " : " + postData.get(id));
} catch (JSONException e) {
e.printStackTrace();
}
}
try {
dos.writeBytes(LINE_FEED);
dos.flush();
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
if (fileList != null && fileList.size() > 0 && !fileList.isEmpty()) {
for (int i = 0; i < fileList.size(); i++) {
File file = new File(fileList.get(i));
if (file != null) ;
addFilePart("photos[" + i + "][image]", file);
}
}
// forming th java.net.URL object
build();
urlConnection.connect();
int statusCode = 0;
try {
urlConnection.connect();
statusCode = urlConnection.getResponseCode();
} catch (EOFException e1) {
if (count < 5) {
urlConnection.disconnect();
count++;
String temp = connectToMULTIPART_POST_service(postName);
if (temp != null && !temp.equals("")) {
return temp;
}
}
} catch (IOException e) {
e.printStackTrace();
}
// 200 represents HTTP OK
if (statusCode == HttpURLConnection.HTTP_OK) {
inputStream = new BufferedInputStream(urlConnection.getInputStream());
strResponse = readStream(inputStream);
} else {
System.out.println(urlConnection.getResponseMessage());
inputStream = new BufferedInputStream(urlConnection.getInputStream());
strResponse = readStream(inputStream);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != inputStream)
inputStream.close();
} catch (IOException e) {
}
}
return strResponse;
}
public void addFormField(String fieldName, String value) {
try {
dos.writeBytes(TWO_HYPHENS + boundary + LINE_FEED);
dos.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\"" + LINE_FEED + LINE_FEED/*+ value + LINE_FEED*/);
/*dos.writeBytes("Content-Type: text/plain; charset=UTF-8" + LINE_FEED);*/
dos.writeBytes(value + LINE_FEED);
} catch (IOException e) {
e.printStackTrace();
}
}
public void addFilePart(String fieldName, File uploadFile) {
try {
dos.writeBytes(TWO_HYPHENS + boundary + LINE_FEED);
dos.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\";filename=\"" + uploadFile.getName() + "\"" + LINE_FEED);
dos.writeBytes(LINE_FEED);
FileInputStream fStream = new FileInputStream(uploadFile);
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int length = -1;
while ((length = fStream.read(buffer)) != -1) {
dos.write(buffer, 0, length);
}
dos.writeBytes(LINE_FEED);
dos.writeBytes(TWO_HYPHENS + boundary + TWO_HYPHENS + LINE_FEED);
/* close streams */
fStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void addHeaderField(String name, String value) {
try {
dos.writeBytes(name + ": " + value + LINE_FEED);
} catch (IOException e) {
e.printStackTrace();
}
}
public void build() {
try {
dos.writeBytes(LINE_FEED);
dos.flush();
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private static String readStream(InputStream in) {
StringBuilder sb = new StringBuilder();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String nextLine = "";
while ((nextLine = reader.readLine()) != null) {
sb.append(nextLine);
}
/* Close Stream */
if (null != in) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
private void createServiceUrl() {
if (null == params) {
return;
}
final Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
boolean isParam = false;
while (it.hasNext()) {
final Map.Entry<String, String> mapEnt = (Map.Entry<String, String>) it.next();
url.append(mapEnt.getKey());
url.append("=");
try {
url.append(URLEncoder.encode(mapEnt.getValue(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
url.append(WSConstants.AMPERSAND);
isParam = true;
}
if (isParam) {
url.deleteCharAt(url.length() - 1);
}
}
}