I've been looking for a way to upload a file using Volley API using the PUT method. All I've seen so far are through MultiPart POST method which aren't applicable to my case.
Assuming I can't change anything on the server side and I'm stuck with using PUT. How do I achieve this in volley?
Note that I only have the url where to upload the file and the file itself.
For uploading image file add the following functions to your StringRequest object.
Here outputFileUri is the Uri of the file which you want to upload.
#Override
public String getBodyContentType() {
return "image/jpeg";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream inputStream = mContext.getContentResolver().openInputStream(outputFileUri);
byte[] b = new byte[8192];
for (int readNum; (readNum = inputStream.read(b)) != -1; ) {
bos.write(b, 0, readNum);
}
inputStream.close();
return bos.toByteArray();
} catch (Exception e) {
Log.d(TAG, e.toString());
}
return null;
}
use the basic concept of PUT method
url = "your URL";
StringRequest putRequest = new StringRequest(Request.Method.PUT, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
Log.d("Response", response);
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error
Log.d("Error.Response", response);
}
}){
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String> ();
params.put("name", "file_name");
return params;
}
}; RequestQueue queue = Volley.newRequestQueue(this);
queue.add(putRequest);
Related
I wanted to upload a file from my android internal storage to Any cloud storage(ex.google drive,One drive etc)since kloudless provides an api to upload file to any cloud storage using accesstoken I wanted to use the same api for uploading the file (https://api.kloudless.com/v1/accounts/accountid+/storage/files/).
I tried it through postman I am able to upload the file
Now I tried through android volley I am able to create the file in the cloud but there is no data inside it. Here is my code
public class MainActivity extends AppCompatActivity {
Button b;
TextView TV;
File myFile;
String responseString;
String path;
public String BASE_URL = "https://api.kloudless.com";
private static final int FILE_SELECT_CODE = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TV = findViewById(R.id.textView);
b = findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showFileChooser();
}
});
}
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) {
// Potentially direct the user to the Market with a Dialog
Toast.makeText(this, "Please install a File Manager.",
Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == FILE_SELECT_CODE) {
if (resultCode == RESULT_OK) {
// Get the Uri of the selected file
Uri uri = data.getData();
Log.d("TAG", "File Uri: " + uri.toString());
// Get the path
String path = null;
try {
path = FileUtils.getPath(this, uri);
} catch (URISyntaxException e) {
e.printStackTrace();
}
Log.d("TAG", "File Path: " + path);
try {
data();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
super.onActivityResult(requestCode, resultCode, data);
}
public void data() throws FileNotFoundException, UnsupportedEncodingException {
final String url = BASE_URL + "/v1/accounts/" + "accountid" + "/storage/files/";
final RequestQueue queue = Volley.newRequestQueue(this);
HashMap<String, Object> params = new HashMap<String, Object>();
params.put( "file","somedata");
JSONObject Body=new JSONObject(params);
final JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url,Body, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// response
Log.d("Response", response.toString());
}
},
new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// error
Log.d("Error.Response", error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
params.put("Authorization", "Bearer Bearerkey");
params.put("Content-Type", "form-data");
params.put("X-Kloudless-Metadata", "{\"parent_id\":\"root\",\"name\":\"testdone.txt\"}");
// params.put("Content-Length", Space);
return params;
}
};
queue.add(request);
}
Please help me how to send the file in body of my request
I work at Kloudless and while I am not very familiar with the Android Volley, the issue here appears to be that you are setting a JSON body with the incorrect content type. In order to replicate the Postman request, you would need to use a multipart file upload instead, as described here: How to upload file using Volley library in android? The file would need to be added to a field called file, e.g entity.addPart("file", new FileBody(new File("....")));
In order for there to be more efficient handling on the server side (for larger files), the request performed should instead include the binary file contents in the request body and have the header Content-Type: application/octet-stream. Based on some cursory searching, it seems like the Volley library doesn't make that very easy so it might be best to try a different library.
Finally found the simple solution to upload a file to api
RequestQueue queue = Volley.newRequestQueue(this);
String url = BASE_URL + "/v1/accounts/" + "353284419" + "/storage/files/";
StringRequest postRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(MainActivity.this, response, Toast.LENGTH_LONG).show();
// response
Log.d("Response", response);
}
},
new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// error
Log.d("Error.Response", error.toString());
}
}
) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Authorization", "Bearer ix7wW4CFJsHxhttg42qsO6HNNRPh06");
params.put("Content-Type", "application/octet-stream");
params.put("X-Kloudless-Metadata", "{\"parent_id\":\"root\",\"name\":\"testing uplodes.pdf\"}");
// params.put("Content-Length", Space);
return params;
}
#Override
public byte[] getBody() throws com.android.volley.AuthFailureError {
File f=new File(path);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] bytesArray = new byte[(int)f.length()];
try {
fis.read(bytesArray);
} catch (IOException e) {
e.printStackTrace();
}
return bytesArray;
};
};
postRequest.setRetryPolicy(new DefaultRetryPolicy(
40000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
queue.add(postRequest);
}
just convert the file into binary array and send it in the body
I need to send 2 files to a server using volley library in Android.
There is an example of how it works well in Postman:
I need to reproduce this exactly POST call in android.
Please take a look of my code for now (which is not working):
JsonObjectRequest sr = new JsonObjectRequest(Request.Method.POST, URL, new JSONObject(params), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i("Response", response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
}
}){
#Override
protected Map<String,String> getParams(){
Map<String,String> params = new HashMap<>();
params.put("Urine", "test");
return params;
}
#Override
public Map<String, String> getHeaders() {
Map<String,String> params = new HashMap<>();
params.put("Authorization", "token");
return params;
}
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=utf-8";
}
#Override
public byte[] getBody() {
int size = (int) file.length();
byte[] bytes = new byte[size];
try {
BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
buf.read(bytes, 0, bytes.length);
buf.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return bytes;
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
byte[] data = response.data;
String message = new String(data);
Log.i("parseNetworkResponse", String.valueOf(message));
return super.parseNetworkResponse(response);
}
};
How can I implement this using Volley library? Thanks.
Retrofit 2 in my opinion has been a much better and easier library to work with for file uploading.
Here is a nice and easy tut to work through. It should assist you.
Retrofit 2 - Multifile Uploading
I'm having some trouble getting JSON response from Microsoft custom vision API (Optical Character Recognition API) when using Android Volley request.
I have used this approach with other API's without any problems, but for this API I cant get it to work.
String URL = "https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/ocr";
final ProgressDialog pDialog = new ProgressDialog(this);
pDialog.setMessage("Getting License plate...");
pDialog.setCancelable(false);
pDialog.show();
try {
RequestQueue requestQueue = Volley.newRequestQueue(this);
JSONObject jsonBody = new JSONObject();
jsonBody.put("url", "https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Atomist_quote_from_Democritus.png/338px-Atomist_quote_from_Democritus.png");
final String requestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
pDialog.hide();
Log.i("VOLLEY", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
}
}) {
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("Ocp-Apim-Subscription-Key", "123124123123123123213");
return headers;
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
}
I'm getting this response back:
E/Volley: [2163] BasicNetwork.performRequest: Unexpected response code 400 for https://westcentralus.api.cognitive.microsoft.com/vision/v1.0/ocr
When using postman I'm not getting any errors.
So hope you can see what I'm doing wrong.
Let me know if you want me to elaborate on anything.
Thanks!
You have to replace StringRequest with JsonObjectRequest and get rid of the Content-type header.
This works for me:
final JSONObject jsonBody = new JSONObject();
jsonBody.put("url", "https://pbs.twimg.com/profile_images/808958766628605952/yB14UlXl_400x400.jpg");
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, URL, jsonBody,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
String readableError = "";
try {
readableError = new String(error.networkResponse.data, "utf-8");
System.out.println(readableError);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<>();
headers.put("Ocp-Apim-Subscription-Key", "XXXXXXXX");
return headers;
}
};
note we had problems on older devices weirdly.
Was caused by the uploaded image being too big.
Api just returns 400 with no explanation.
ImageHelper class has code to resize image
I wanna send a PDF file stored in internal storage ( InternalStrorage/PDF/OCK.pdf )
I already sent String Data to my php server using Android Volley without problems via this function:
private void upload(){
StringRequest stringRequest = new StringRequest(Request.Method.POST, UploadURL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
String Response = jsonObject.getString("response");
Toast.makeText(getApplicationContext(),Response, Toast.LENGTH_LONG).show();
selectedimage.setImageResource(0);
selectedimage.setVisibility(View.GONE);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}
){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("date",DateFormat.getDateTimeInstance().format(new Date()).toString());
params.put("description",editTextDescription.getText().toString());
params.put("statut", whatstatutis());
params.put("action",editTextImediatActionTaken.getText().toString());
return params;
}
};
MySingleton.getInstance(getApplicationContext()).addTorequesteque(stringRequest);
}
I wanna send the PDF file with my data in the same time.
Finally i find the solution.
1- Just convert the PDF to to byte array
2- Byte Array to base64
3- Send it like normal strings
byte[] data = null;
File filessss = new File(Link_Of_The_PDF.pdf);
try {
data = FileUtils.readFileToByteArray(filessss);
} catch (IOException e) {
e.printStackTrace();
}
return Base64.encodeToString(data, Base64.DEFAULT);
I am trying to use DWorkS/VolleyPlus to make a MultiPartRequest.
I have searched through the GitHub repository, and it's sample code, but I can find no examples using this class.
I am getting a 411 response code when I make my request. My understanding is that this is sent by the server as a response when it refuses to accept a message without a content-length header. How would I go about providing this?
Below is the relevant part of the LogCat showing the error, and my method.
Looking at the code for MultiPartRequest, it has a field called isFixedStreamingMode. This name sounds similar to setFixedLengthStreamingMode for a connection, however I can't see where it ever gets used in the code. Also it is a boolean not an int, so I cannot supply a length with it. Does anyone know what this field is for?
Has anyone successfully used MultiPartRequest from this library? Any advice or examples would be greatly appreciated.
I am currently successfully making POST, GET and PUT methods using the StringRequest class from this library.
LogCat
03-11 22:17:15.388 25236-25236/au.com.xxx.yyy D/MainActivity﹕ postMyItem: http://yyy.zzz.com.au/api/v1/my_item
03-11 22:17:15.507 25236-25309/au.com.xxx.yyy E/Volley﹕ [5861] BasicNetwork.performRequest: Unexpected response code 411 for http://yyy.zzz.com.au/api/v1/my_item
03-11 22:17:15.508 25236-25236/au.com.xxx.yyy D/MainActivity﹕ error response: <html>
<head><title>411 Length Required</title></head>
<body bgcolor="white">
<center><h1>411 Length Required</h1></center>
<hr><center>nginx/1.1.19</center>
</body>
</html>
03-11 22:17:15.508 25236-25236/au.com.xxx.yyy D/MainActivity﹕ Volley Error: com.android.volley.error.VolleyError
Method
public void postMyItem(final MyItem myItem) {
String url = getString(R.string.url__server_api) + getString(R.string.post__my_item);
MultiPartRequest request = new MultiPartRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Volley POST MyItem response: " + response);
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "Volley Error: " + error);
try {
String response = new String(error.networkResponse.data, "utf-8");
Log.d(TAG, "error response: " + response);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
})
{
#Override
protected Response parseNetworkResponse(NetworkResponse networkResponse) {
return null;
}
#Override
public Map<String, String> getHeaders() throws com.android.volley.error.AuthFailureError {
Map<String, String> map = new HashMap<>();
map.put(getString(R.string.header_field__access_token), mAccess_token);
return map;
}
};
if (myItem.name != null) {
request.addMultipartParam("name", "multipart/mixed", myItem.name);
}
if (myItem.quantity != null) {
request.addMultipartParam("quantity", "multipart/mixed", myItem.quantity);
}
...
//TODO: request.addFile(name, filePath)
VolleySingleton.getInstance(this).addToRequestQueue(request);
}
So sometime the servers might require content length to be told before uploading imagesetFixedStreamingMode is the method. The sample code is below
SimpleMultipartRequest request = new SimpleMultipartRequest(Method.POST, apiUrl, mListener, mErrorListener);
request.addFile("photo", image_path);
RequestQueue mRequestQueue = Volley.newRequestQueue(getApplicationContext());
mRequestQueue.add(request);
mRequestQueue.setFixedStreamingMode(true);
mRequestQueue.start();
You can use MultipartEntitiy in volley request for adding multipart data in your request body, by overriding getBody method like this:
public class MultipartRequest extends Request<String> {
private MultipartEntity entity = new MultipartEntity();
private static final String FILE_PART_NAME = "file";
private static final String STRING_PART_NAME = "text";
private static final String SELFIE_IMAGE = "selfieImage";
private static final String SELFIE_CAPTION = "cap";
private final Response.Listener<String> mListener;
private final File mFilePart;
private final String mStringPart;
public MultipartRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, File file, String stringPart)
{
super(Method.POST, url, errorListener);
mListener = listener;
mFilePart = file;
mStringPart = stringPart;
buildMultipartEntity();
}
private void buildMultipartEntity()
{ System.out.println("buildMultipartEntity");
entity.addPart(SELFIE_IMAGE, new FileBody(mFilePart));
try
{
entity.addPart(SELFIE_CAPTION, new StringBody(mStringPart));
}
catch (UnsupportedEncodingException e)
{
VolleyLog.e("UnsupportedEncodingException");
}
}
#Override
public String getBodyContentType()
{ System.out.println("getBodyContentType");
return entity.getContentType().getValue();
}
#Override
public byte[] getBody() throws AuthFailureError{
System.out.println("getBody");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
entity.writeTo(bos);
}
catch (IOException e)
{
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
return Response.success("Uploaded", getCacheEntry());
}
#Override
protected void deliverResponse(String response)
{
mListener.onResponse(response);
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
System.out.println("getHeaders");
if (headers == null
|| headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
AppController.getInstance().addSessionCookie(headers);
return headers;
}
}