How to read multipart response, sent from resteasy to android, using okHttp? - android

I want to upload list of files (images in my case) from JBoss server to android.
I am doing so by the below written code:
#GET
#Path("/report/{filename}")
#Produces({MediaType.MULTIPART_FORM_DATA})
public MultipartFormDataOutput getReport(#PathParam("filename") String filename, #Context HttpServletRequest request) {
try {
String token = request.getHeader("Authorization");
List<File> file = processImage.getImage(filename,token);
MultipartFormDataOutput output = new MultipartFormDataOutput();
for(File image: file){
System.out.println("class of this" +image + "MMMM" +image.exists());
output.addPart(image, new MediaType("image","jpg"));
}
return output;
} .....
.......
}
On Android side I want to read the response (the files in multipart form). I am using okHttp to make the connection.
Searching a lot on internet I tried the below code to read the multipart response, but it is not working. It seems that is not reading anything from the stream.
ByteArrayDataSource ds = new ByteArrayDataSource(response.body().byteStream(), "multipart/form-data");
MimeMultipart multipart = new MimeMultipart(ds);
BodyPart jsonPart = multipart.getBodyPart(0);
System.out.println("Response body = " + jsonPart.getInputStream());
File reportFile = new File(Environment.getExternalStorageDirectory() + File.separator + "downloadedFile.jpg");
InputStream is = jsonPart.getInputStream();
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(reportFile);
byte[] buffer = new byte[MEGABYTE];
int bufferLength = 0;
while ((bufferLength = is.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, bufferLength);
}
is.close();
fileOutputStream.close();
.......
}
Can anyone please help me solving this. I am stuck here from 2 days. What am I doing wrong .

You can do the following:
Create an async task to run in the background
Use okhttp3.Request to create the request
Create OkHttpClient to send the request and save the response in okHttp3 Response
Then get the response body from the okhttp3.ResponseBody and use InputStreamReader and BufferedReader to read the files.
Something like following should work:
private class FileTask extends AsyncTask<Void, Void, Void> {
private File file = null;
#Override
protected Void doInBackground(Void... params) {
okhttp3.Request request = new okhttp3.Request.Builder()
.url("Your URL for getReport()")
.get()
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder().
connectTimeout(80, TimeUnit.SECONDS)
.writeTimeout(80, TimeUnit.SECONDS)
.readTimeout(80, TimeUnit.SECONDS)
.build();
try {
Response response = okHttpClient.newCall(request).execute();
okhttp3.ResponseBody in = response.body();
InputStream is = in.byteStream();
InputStreamReader inputStreamReader = new InputStreamReader(is);
BufferedReader buffReader = new BufferedReader(inputStreamReader);
file = new File(Environment.getExternalStorageDirectory() + File.separator + "filename.txt"); //Your output file
OutputStream output = new FileOutputStream(file);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(output);
String line=buffReader.readLine();
while ((line=buffReader.readLine()) != null) {
output.write(line.getBytes());
output.write('\n');
}
buffReader.close();
output.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
//do post execution steps
}
}
}

Are you possibly using HttpLoggingInterceptor with setLevel(HttpLoggingInterceptor.Level.BODY)? I used your code to successfully parse a multipart response. But once I change the level from HEADERS to BODY, that code no longer works, and acts as if it is not reading anything from the stream. I already reported the issue: https://github.com/square/okhttp/issues/3269
By the way, thanks for giving me sample code to allow me to parse a multipart body with OkHttp. For others who may come along, I had to add this to my maven pom.xml:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.6</version>
</dependency>

try this:
//first you should convert image into bytearray
VolleyMultipartRequest multipartRequest = new VolleyMultipartRequest(Request.Method.POST, url, new Response.Listener<NetworkResponse>() {
#Override
public void onResponse(NetworkResponse response) {
System.out.println(" response"+response.data);
String resultResponse = new String(response.data);
System.out.println("------------- response-----------------"+resultResponse);
try {
JSONObject jsonObject = new JSONObject(resultResponse);
sStatus = jsonObject.getString("status");
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
dialog.dismiss();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
dialog.dismiss();
NetworkResponse networkResponse = error.networkResponse;
String errorMessage = "Unknown error";
if (networkResponse == null) {
if (error.getClass().equals(TimeoutError.class)) {
errorMessage = "Request timeout";
} else if (error.getClass().equals(NoConnectionError.class)) {
errorMessage = "Failed to connect server";
}
} else {
String result = new String(networkResponse.data);
try {
JSONObject response = new JSONObject(result);
String status = response.getString("status");
String message = response.getString("message");
Log.e("Error Status", status);
Log.e("Error Message", message);
if (networkResponse.statusCode == 404) {
errorMessage = "Resource not found";
} else if (networkResponse.statusCode == 401) {
errorMessage = message + " Please login again";
} else if (networkResponse.statusCode == 400) {
errorMessage = message + " Check your inputs";
} else if (networkResponse.statusCode == 500) {
errorMessage = message + " Something is getting wrong";
}
} catch (JSONException e) {
e.printStackTrace();
}
}
Log.i("Error", errorMessage);
error.printStackTrace();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<>();
params.put("id",ID);
System.out.println("id---------------"+ID);
return params;
}
#Override
protected Map<String, DataPart> getByteData() {
Map<String, DataPart> params = new HashMap<>();
params.put("image",new DataPart("imnage.jpg", byteArray));
return params;
}
}
AppController.getInstance().addToRequestQueue(multipartRequest);
}

Related

Upload large file to server android

I tried to upload a large file to a server (the max file size supported is 128Mb). If I correctly understood, the server can receive large files (for example 500Mb) but only if these files are sent in chunks.
I wrote the method bellow and expected it to upload video files in chunks to the server. However, I am getting the following error from the server:
413 Request Entity Too Large
Bellow is my method:
public static void uploadFile(Context context, Uri videoUri, String fileName, File file) throws FileNotFoundException {
int CHUNK_SIZE = 2048;
ContentResolver contentResolver = context.getContentResolver();
final String contentType = contentResolver.getType(videoUri);
final AssetFileDescriptor fd = contentResolver.openAssetFileDescriptor(videoUri, "r");
if (fd == null) {
try {
throw new FileNotFoundException("could not open file descriptor");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
RequestBody videoFile = new RequestBody() {
#Override
public long contentLength() {
return fd.getDeclaredLength();
}
#Override
public MediaType contentType() {
return MediaType.parse(contentType);
}
#Override
public void writeTo(BufferedSink sink) throws IOException {
Source source = null;
try {
source = Okio.source(file);
long total = 0;
long read;
while ((read = source.read(sink.buffer(), CHUNK_SIZE)) != -1) {
total += read;
sink.flush();
Log.e("progress", String.valueOf(total/100/100/100));
//this.listener.transferred(total);
}
} finally {
Util.closeQuietly(source);
}
}
};
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("video/*", fileName, videoFile)
.build();
Request request = new Request.Builder()
.url("https://test.ua/api/upload")
.post(requestBody)
.header("Authorization", Utils.getHeaderToken())
.build();
OkHttpClient client = new OkHttpClient.Builder().build();
client.newCall(request).enqueue(new Callback() {
#Override public void onFailure(Call call, IOException e) {
try {
fd.close();
} catch (IOException ex) {
e.addSuppressed(ex);
}
Log.e("asdasd", "failed", e);
}
#Override public void onResponse(Call call, Response response) throws IOException {
Log.e("success", String.valueOf(response.code()));
InputStream in = response.body().byteStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String result, line = reader.readLine();
result = line;
while((line = reader.readLine()) != null) {
result += line;
}
Log.e("success", String.valueOf(result));
fd.close();
}
});
}
UPD:
server use laravel-chunk-upload and they have this settings in frontend:
dropzoneOptions: {
url: '/upload',
dictDefaultMessage: 'Click here',
chunksUploaded: function (file, done) {
done()
},
thumbnailWidth: 150,
maxFilesize: 250,
chunking: false,
chunkSize: 1000000, // Bytes
required: true,
maxFiles: 1,
acceptedFiles: 'video/*',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
},

Getting java.net.SocketTimeoutException alwayse in downloading files with OkHttp

I am using OkHttp to download a file from the server.
And this is my code:
I set read and write timeout for it:
public static final String API_BASE_URL = "http://XXXX:8080/tablet/";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.connectTimeout(60,TimeUnit.SECONDS)
.writeTimeout(60,TimeUnit.SECONDS);
This is my createServiceFile:
public static <S> S createServiceFile(Class<S> serviceClass, final String token) {
if (token != null) {
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", token)
.header("Accept", "text/html,application/xhtml+xml,application/pdf,application/xml;q=0.9," +
"image/webp,audio/mpeg ,image/png,audio/mp4,image/jpeg,*/*;q=0.8")
.method(original.method(), original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = builder.client(client).build();
return retrofit.create(serviceClass);
}
And this is my code that I write the response to SD Card (in response contentLength is -1 because the server doesn't send it to me):
public DownloadRequest DownloadFile() {
//Creating folder for Application in SD Card if it's not created yet in App Class!
new java.io.File(G.DIR_APP).mkdirs();
new java.io.File(G.DIR_MEDIA).mkdirs();
APIService downloadService = ServiceGenerator.createServiceFile(APIService.class, G.TOKEN);
downloadService.downloadFileWithDynamicUrlSync(url)//set URL of the file
.subscribeOn(Schedulers.newThread())
.observeOn(Schedulers.io())
.delay(30, TimeUnit.MILLISECONDS)
.subscribe(new Observer<ResponseBody>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(ResponseBody responseBody) {
Log.i(TAG, "On Next And Current App is: " + fileName);
if (writeResponseBodyToDisk(responseBody)) {
Log.i(TAG, fileName + "Downloaded successful");
//This Download was successful Then try to set downloadResult true
result = true;
} else {
result = false;
}
}
#Override
public void onError(Throwable e) {
Log.i(TAG, "!!!!!!!!!!!!!!!!\n\nOn Error And Current App is: " +
fileName + " And Error is" + e.toString() + "\n\n!!!!!!!!!!!!!!!!\n\n");
//Set downloadResult false
result = false;
if (listener != null) {
listener.onDownloadCompleteListener(false);
}
}
#Override
public void onComplete() {
Log.i(TAG, "On Complete And Current App is: " + fileName);
if (listener != null) {
if (result) {
listener.onDownloadCompleteListener(true);
} else {
listener.onDownloadCompleteListener(false);
}
}
}
});
return this;
}
And this code will write response to disck:
private boolean writeResponseBodyToDisk(ResponseBody body) {
// Location to save downloaded file and filename
java.io.File file = new java.io.File(destinationPath + fileName + "." + extension);
try {
InputStream inputStream = null;
OutputStream outputStream = null;
int bytesBuffered = 0;
try {
byte[] fileReader = new byte[bufferSize];
downloadSize = 0;
inputStream = body.byteStream();
/*
* If append requested we have to append new bytes to
* Exists bytes on the storage
*/
if (appendNeed) {
outputStream = new FileOutputStream(file, true);
} else {
outputStream = new FileOutputStream(file);
}
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
bytesBuffered += read;
if (bytesBuffered > 1024 * 1024) {
// outputStream.write(fileReader, 0, read);
outputStream.flush();
bytesBuffered = 0;
}
outputStream.write(fileReader, 0, read);
downloadSize += read;
percent = (int) (100.0f * (float) downloadSize / totalSize);
if (listener != null) {
listener.onDownloadPercentListener(percent);
}
}
outputStream.flush();
inputStream.close();
outputStream.close();
return true;
} catch (IOException e) {
Log.i(TAG, "Error in download" + e.toString());
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
Log.i(TAG, "Error in download" + e.toString());
return false;
}
}
But I get false from this method (writeResponseBodyToDisk)with error of
java.net.SocketTimeoutException while the file is downloaded correctly!
I think this problem it about contentLength that is -1 for me.
Thank you for your answers.

Download HTML file from URL using Retrofit

I am getting a URL in response. I want to download the html of that URL so that user can see it offline also. Its a recyclerView in which each items contain a URL. So when user clicks on the URL of one item it should save it in external disk.
Below is the code:
NewsAdapter:
case R.id.save:
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.nytimes.com/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Log.i("Retrofit build", "initiated");
ApiInterface retrofitInterface = retrofit.create(ApiInterface.class);
final Call< ResponseBody > call = retrofitInterface.downloadFileWithDynamicUrlSync("2017/09/13/us/nursing-home-deaths-florida.html");
Log.i("Retrofit req execute", "initiated");
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... voids) {
boolean writtenToDisk = false;
try {
writtenToDisk = writeResponseBodyToDisk(call.execute().body());
} catch (IOException e) {
e.printStackTrace();
}
;
Log.d("success", "file download was a success? " + writtenToDisk);
return null;
}
}.execute();
break;
private boolean writeResponseBodyToDisk(ResponseBody body) {
try {
// todo change the file location/name according to your needs
File futureStudioIconFile = new File(Environment.DIRECTORY_DOWNLOADS + File.separator + "Future Studio Icon.png");
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
long fileSize = body.contentLength();
long fileSizeDownloaded = 0;
inputStream = body.byteStream();
outputStream = new FileOutputStream(futureStudioIconFile);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
fileSizeDownloaded += read;
Log.d("filedownload", "file download: " + fileSizeDownloaded + " of " + fileSize);
}
outputStream.flush();
return true;
} catch (IOException e) {
return false;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return false;
}
}
ApiInterface:
// option 2: using a dynamic URL
#Streaming
#GET
Call<ResponseBody> downloadFileWithDynamicUrlSync(#Url String fileUrl);
I am also getting the error:
Failed to invoke public com.squareup.okhttp.ResponseBody() with no args
Can someone tell me how to implement it correctly.
Use URL with domain name to download file.Remove streaming annotation don't need that.
You are not receiving file body as you are not using complete URL.
Create an interface like this
#GET
Call<ResponseBody> downloadFile(#Url String url);
Then use this code :
public void onResponse(Call<ResponseBody> call, Response<ResponseBody>
response)
{
if (response.isSuccessful()) {
String filePath = Utils.downloadFile(response.body(),"filename");
}
}
public String downloadFile(ResponseBody body, String fileName) {
String filePath = null;
try {
int count;
byte data[] = new byte[1024 * 4];
InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
File storageDir = new File(Environment.getExternalStorageDirectory(), "AppName");
if (!storageDir.exists()) {
storageDir.mkdirs();
}
File outputFile = new File(storageDir, fileName);
OutputStream output = new FileOutputStream(outputFile);
while ((count = bis.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
bis.close();
filePath = outputFile.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
}
return filePath;
}

HttpUrlConnection does not work on mobile device but on emulator

all of a sudden my mobile device can't connect to the local server anymore. async tasks are not executed and i just can't figure out why. slowly i'm getting really desperate because in my opinion i didn't change anything to cause this.
as an example, this is a background task which is not working
public class Login extends AsyncTask<String, Void, String>{
private String loginUrl = "http://...";
private int loginSuccess = 0;
public String getToken(String fromJson) throws JSONException {
JSONObject json = new JSONObject(fromJson);
if(json.has("api_authtoken")) {
loginSuccess = 1;
String appToken = json.getString("api_authtoken");
return appToken;
}
else {
return json.toString();
}
}
public String doInBackground(String... arg0) {
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String authToken;
try {
// get logged in to get the api_authtoken
String email = (String) arg0[0];
String password = (String) arg0[1];
URL url = new URL(loginUrl);
// Create the request and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
//put values of edittexts into json-Object
JSONObject data = new JSONObject();
try {
data.put("email", email);
data.put("password", password);
} catch(JSONException e) {
Log.e("EXCEPTION", "unexpected JSON exception", e);
e.printStackTrace();
}
urlConnection.connect();
OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
wr.write(data.toString());
wr.flush();
reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
//read server response
while((line = reader.readLine()) != null) {
sb.append(line);
}
//receive server "answer"
try {
return getToken(sb.toString());
}catch(JSONException e) {
Log.e("LOG", "unexpected JSON exception", e);
e.printStackTrace();
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("MainActivity", "Error closing stream", e);
}
}
}
//return sb.toString();
return null;
}
catch(IOException e) {
Log.e("LoginTask", "Error ", e);
// If the code didn't successfully get the data, there's no point in attempting
// to parse it.
//forecastJsonStr = null;
return null;
}
}
public void onPostExecute(String result) {
super.onPostExecute(result);
//Log.v("RESULT", result);
if(result == null) {
CharSequence text = "no internet connection";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(MainActivity.this, text, duration);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
}
if(loginSuccess == 0) {
// if the request wasn't successful
// give user a message via toast
CharSequence text = "wrong password or user. please try again";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(MainActivity.this, text, duration);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
}
else {
// save token in shared preferences
SharedPreferences tokenPref = getSharedPreferences(getString(R.string.preference_token), Context.MODE_PRIVATE);
SharedPreferences.Editor editorToken = tokenPref.edit();
editorToken.putString(getString(R.string.saved_auth_token), result);
editorToken.commit();
//save login status = 1 in shared preferences
SharedPreferences loginPref = getSharedPreferences(getString(R.string.preference_logged_in), Context.MODE_PRIVATE);
SharedPreferences.Editor editorLogin = loginPref.edit();
editorLogin.putString(getString(R.string.saved_login), "1");
editorLogin.commit();
Intent mapsIntent = new Intent(getApplicationContext(), MapsActivity.class);
startActivity(mapsIntent);
}
}
}
HttpClient is not supported any more in sdk 23. You have to use URLConnection or downgrade to sdk 22 (compile 'com.android.support:appcompat-v7:22.2.0')
If you need sdk 23, add this to your gradle:
android {
useLibrary 'org.apache.http.legacy'
}
HttpClient won't import in Android Studio
You should think about using a HTTP library, there is a bunch of them on internet, some are really easy to use, optimize and errorless.
For example, Volley (made by Google, I really like this one), okHttp or Picasso (for image).
You should take a look at this.
If you want to send (output), for example with POST or PUT requests you need to use this :-
urlConnection.setDoOutput(true);
In your code :-
public class Login extends AsyncTask<String, Void, String>{
private String loginUrl = "http://...";
private int loginSuccess = 0;
public String getToken(String fromJson) throws JSONException {
JSONObject json = new JSONObject(fromJson);
if(json.has("api_authtoken")) {
loginSuccess = 1;
String appToken = json.getString("api_authtoken");
return appToken;
}
else {
return json.toString();
}
}
public String doInBackground(String... arg0) {
// so that they can be closed in the finally block.
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String authToken;
try {
// get logged in to get the api_authtoken
String email = (String) arg0[0];
String password = (String) arg0[1];
URL url = new URL(loginUrl);
// Create the request and open the connection
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setDoOutput(true); // HERE
//put values of edittexts into json-Object
JSONObject data = new JSONObject();
try {
data.put("email", email);
data.put("password", password);
} catch(JSONException e) {
Log.e("EXCEPTION", "unexpected JSON exception", e);
e.printStackTrace();
}
OutputStreamWriter wr = new OutputStreamWriter(urlConnection.getOutputStream());
wr.write(data.toString());
wr.flush();
urlConnection.connect();
reader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line = null;
//read server response
while((line = reader.readLine()) != null) {
sb.append(line);
}
//receive server "answer"
try {
return getToken(sb.toString());
}catch(JSONException e) {
Log.e("LOG", "unexpected JSON exception", e);
e.printStackTrace();
} finally{
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e("MainActivity", "Error closing stream", e);
}
}
}
//return sb.toString();
return null;
}
catch(IOException e) {
Log.e("LoginTask", "Error ", e);
// If the code didn't successfully get the data, there's no point in attempting
// to parse it.
//forecastJsonStr = null;
return null;
}
}
public void onPostExecute(String result) {
super.onPostExecute(result);
//Log.v("RESULT", result);
if(result == null) {
CharSequence text = "no internet connection";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(MainActivity.this, text, duration);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
}
if(loginSuccess == 0) {
// if the request wasn't successful
// give user a message via toast
CharSequence text = "wrong password or user. please try again";
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(MainActivity.this, text, duration);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
}
else {
// save token in shared preferences
SharedPreferences tokenPref = getSharedPreferences(getString(R.string.preference_token), Context.MODE_PRIVATE);
SharedPreferences.Editor editorToken = tokenPref.edit();
editorToken.putString(getString(R.string.saved_auth_token), result);
editorToken.commit();
//save login status = 1 in shared preferences
SharedPreferences loginPref = getSharedPreferences(getString(R.string.preference_logged_in), Context.MODE_PRIVATE);
SharedPreferences.Editor editorLogin = loginPref.edit();
editorLogin.putString(getString(R.string.saved_login), "1");
editorLogin.commit();
Intent mapsIntent = new Intent(getApplicationContext(), MapsActivity.class);
startActivity(mapsIntent);
}
}
}

okhttp multipart image upload with file name

i am trying to upload a image to server from an android phone. this is what i have done so far
OkHttpClient client = new OkHttpClient();
MultipartBuilder builder = new MultipartBuilder();
builder.type(MultipartBuilder.FORM).addPart(RequestBody.create(MediaType.parse("application/json; charset=utf-8"), requestPackage.getJsonParam().toString()));
for (int i = 0; i < requestPackage.getPics().size(); i++) {
builder.addPart(RequestBody.create(MediaType.parse("image/png"/* + i*/), new File(URI.create(requestPackage.getPics().get(i)))));
Log.i("image to upload",URI.create(requestPackage.getPics().get(i)).toString());
}
requestBody = builder.build();
Request request = new Request.Builder().url(requestPackage.getUri()).post(requestBody).build();
try {
response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
// System.out.println(response.body().string());
return response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
how do i add names to the different parts.because if there is no name(key) to them then how will server side guy store it?
Get OkHttp 2.1, and use MultipartBuilder.addFormDataPart() which takes the filename as a parameter.
The syntax seems to have changed a bit since the previous answers. I'm using OkHttp 3.2.0.
public void upload(String url, File file) throws IOException {
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("image/png"), file))
.addFormDataPart("other_field", "other_field_value")
.build();
Request request = new Request.Builder().url(url).post(formBody).build();
Response response = this.client.newCall(request).execute();
}
You can find all in the official document: https://github.com/square/okhttp/wiki/Recipes
Especially you will be interested in folowing piece from Posting a multipart request:
RequestBody requestBody = new MultipartBuilder()
.type(MultipartBuilder.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
.build();
Here is a complete solution, of how to upload a file using okhttp3.
Firstly, add a file picker with a button on click listener to your code like this:
A button to pick file:
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_choose_file:
showFileChooser();
break;
}
}
private String filePath = null;
private File sourceFile;
private static final int FILE_SELECT_CODE = 0;
private void showFileChooser() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");
intent.addCategory(Intent.CATEGORY_OPENABLE);
try {
startActivityForResult(
Intent.createChooser(intent, "Select a File to Upload"),
FILE_SELECT_CODE);
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}
}
Then handle onActivityResult like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case FILE_SELECT_CODE:
if (resultCode == RESULT_OK) {
// Get the Uri of the selected file
Uri uri = data.getData();
File file = new File(getCacheDir(), getFileName(uri));
int maxBufferSize = 1 * 1024 * 1024;
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
Log.e("InputStream Size","Size " + inputStream);
int bytesAvailable = inputStream.available();
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
final byte[] buffers = new byte[bufferSize];
FileOutputStream outputStream = new FileOutputStream(file);
int read = 0;
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
Log.e("File Size","Size " + file.length());
inputStream.close();
outputStream.close();
file.getPath();
Log.e("File Path","Path " + file.getPath());
file.length();
Log.e("File Size","Size " + file.length());
if(file.length() > 0){
sourceFile = file;
filePath = sourceFile.getPath();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
} else {
}
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
private String getMimeType(String path) {
FileNameMap fileNameMap = URLConnection.getFileNameMap();
String contentTypeFor = fileNameMap.getContentTypeFor(path);
if (contentTypeFor == null)
{
contentTypeFor = "application/octet-stream";
}
return contentTypeFor;
}
public String getFileName(Uri uri) {
String result = null;
if (uri.getScheme().equals("content")) {
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
try {
if (cursor != null && cursor.moveToFirst()) {
result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}
} finally {
cursor.close();
}
}
if (result == null) {
result = uri.getPath();
int cut = result.lastIndexOf('/');
if (cut != -1) {
result = result.substring(cut + 1);
}
}
return result;
}
Finally, handle the file upload along with other needed information like this :
try {
UpdateInformation("yourEmailAddress", filePath, sourceFile);
} catch (IOException e) {
e.printStackTrace();
}
private void UploadInformation(String email, final String _filePath, final File file) throws IOException {
runOnUiThread(new Runnable() {
#Override
public void run() {
//show progress bar here
}
});
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS)
.build();
String mime = getMimeType(_filePath);
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse(mime), file))
.addFormDataPart("email", email)
.build();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("yourEndPointURL")
.post(body)
.addHeader("authorization", "yourEndPointToken")
.addHeader("content-type", "application/json")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
call.cancel();
runOnUiThread(new Runnable() {
#Override
public void run() {
//hide progress bar here
}
});
}
#Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
try {
final String myResponse = response.body().string();
runOnUiThread(new Runnable() {
#Override
public void run() {
//hide progress bar here
//Cont from here
//Handle yourEndPoint Response.
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Note: Don't forget to add this permission to the manifest file.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
You can use multipart like below to send multiple values in single request
HttpPost httppost = new HttpPost(mPostURL);
MultipartEntity entity = new MultipartEntity();
entity.addPart("value", new StringBody("upload", Charset.forName("UTF-8")));
File myFile = new File(mFilePath);
FileBody fileBody = new FileBody(filePath);
entity.addPart("file", fileBody);
entity.addPart("filename", new StringBody("fileName", Charset.forName("UTF-8")));
httppost.setEntity(entity);
HttpClient httpClient = new DefaultHttpClient();

Categories

Resources