Suba una imagen usando Google Volley

Tendría que cargar una imagen de la aplicación, que estoy desarrollando, al servidor y me gustaría saber cómo puedo desarrollar la solicitud de varias partes para cargar la imagen con Google Volley.

Gracias

Tengo un ejemplo para subir imágenes de Google Volley . Echar un vistazo:

 package net.colaborativa.exampleapp.api; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import com.android.volley.AuthFailureError; import com.android.volley.NetworkResponse; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.Response.ErrorListener; import com.android.volley.Response.Listener; import com.android.volley.VolleyLog; import com.android.volley.toolbox.HttpHeaderParser; public class PhotoMultipartRequest extends Request { private static final String FILE_PART_NAME = "file"; private MultipartEntityBuilder mBuilder = MultipartEntityBuilder.create(); private final Response.Listener mListener; private final File mImageFile; protected Map headers; public PhotoMultipartRequest(String url, ErrorListener errorListener, Listener listener, File imageFile){ super(Method.POST, url, errorListener); mListener = listener; mImageFile = imageFile; buildMultipartEntity(); } @Override public Map getHeaders() throws AuthFailureError { Map headers = super.getHeaders(); if (headers == null || headers.equals(Collections.emptyMap())) { headers = new HashMap(); } headers.put("Accept", "application/json"); return headers; } private void buildMultipartEntity(){ mBuilder.addBinaryBody(FILE_PART_NAME, mImageFile, ContentType.create("image/jpeg"), mImageFile.getName()); mBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); mBuilder.setLaxMode().setBoundary("xx").setCharset(Charset.forName("UTF-8")); } @Override public String getBodyContentType(){ String contentTypeHeader = mBuilder.build().getContentType().getValue(); return contentTypeHeader; } @Override public byte[] getBody() throws AuthFailureError{ ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { mBuilder.build().writeTo(bos); } catch (IOException e) { VolleyLog.e("IOException writing to ByteArrayOutputStream bos, building the multipart request."); } return bos.toByteArray(); } @Override protected Response parseNetworkResponse(NetworkResponse response) { T result = null; return Response.success(result, HttpHeaderParser.parseCacheHeaders(response)); } @Override protected void deliverResponse(T response) { mListener.onResponse(response); } } 

Y puedes usarlo así:

 RequestQueue mQueue = Volley.newRequestQueue(context); PhotoMultipartRequest imageUploadReq = new PhotoMultipartRequest(url, ErrorListener, Listener, imageFile); mQueue.add(imageUploadReq); 

Espero que estos códigos te inspiren.

La respuesta de @silverknight funciona, sin embargo, también tuve que agregar lo siguiente en build.gradle para resolver httpcomponents dependencias de httpcomponents :

 android { ... // have to exclude these otherwise you'll get: // Error:Gradle: Execution failed for task: ... com.android.builder.packaging.DuplicateFileException: ... packagingOptions { exclude 'META-INF/NOTICE' exclude 'META-INF/LICENSE' exclude 'META-INF/DEPENDENCIES' } } dependencies { ... compile 'com.android.volley:volley:1.0.0' compile('org.apache.httpcomponents:httpmime:4.3.6') { exclude module: 'httpclient' } compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1' } 

NOTA: No use org.apache.httpcomponents: httpclient

Debe evitar el uso de la versión estándar de 'org.apache.httpcomponents:httpclient:4.5.2'

Si intentas:

 android { ... } dependencies { ... compile 'com.android.volley:volley:1.0.0' compile 'org.apache.httpcomponents:httpcore:4.4.4' compile 'org.apache.httpcomponents:httpmime:4.5.2' compile('org.apache.httpcomponents:httpclient:4.5.2' } 

conseguirás:

 java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/message/BasicHeaderValueFormatter; in class Lorg/apache/http/message/BasicHeaderValueFormatter; or its superclasses (declaration of 'org.apache.http.message.BasicHeaderValueFormatter' appears in /system/framework/ext.jar) 

o algo similar a los comentarios existentes [1] [2] [3] .

Deberías usar el puerto Android de httpclient , según esta respuesta SO

NOTA: Use org.apache.httpcomponents: httpmime: 4.3.6

Tienes que usar org.apache.httpcomponents:httpmime:4.3.6 , no puedes ir por encima de la versión 4.3.x Por ejemplo, puede sentirse tentado de usar la última versión de httpmime , que en el momento de escribir es 4.5.2 :

 android { ... } dependencies { ... compile('org.apache.httpcomponents:httpmime:4.5.2') { exclude module: 'httpclient' } compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1' 

con esta configuración, obtendrá lo siguiente cuando invoque PhotoMultipartRequest :

 java.lang.NoSuchMethodError: No static method create(Ljava/lang/String;[Lorg/apache/http/NameValuePair;)Lorg/apache/http/entity/ContentType; in class Lorg/apache/http/entity/ContentType; or its super classes (declaration of 'org.apache.http.entity.ContentType' appears in /xxx/base.apk) 

Copié esta clase de https://gist.github.com/ishitcno1/11394069 Le mostraré cómo la usa. Funcionó en mi caso. Copia esta clase Haz los cambios necesarios.

 package com.tagero.watchfriend; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import org.apache.http.HttpEntity; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import android.util.Log; import com.android.volley.AuthFailureError; import com.android.volley.NetworkResponse; import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyLog; public class PhotoMultipartRequest extends Request { static final String TAG = "xxxxxx"; public static final String KEY_PICTURE = "kullanici_resmi"; public static final String KEY_PICTURE_NAME = "kullanici_resmi_dosya_adi"; private HttpEntity mHttpEntity; @SuppressWarnings("rawtypes") private Response.Listener mListener; public PhotoMultipartRequest(String url, String filePath, Response.Listener listener, Response.ErrorListener errorListener) { super(Method.POST, url, errorListener); mListener = listener; mHttpEntity = buildMultipartEntity(filePath); } public PhotoMultipartRequest(String url, File file, Response.Listener listener, Response.ErrorListener errorListener) { super(Method.POST, url, errorListener); mListener = listener; mHttpEntity = buildMultipartEntity(file); } private HttpEntity buildMultipartEntity(String filePath) { File file = new File(filePath); return buildMultipartEntity(file); } private HttpEntity buildMultipartEntity(File file) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); String fileName = file.getName(); logYazdir("fileName : " + fileName); FileBody fileBody = new FileBody(file); builder.addPart(KEY_PICTURE, fileBody); builder.addTextBody(KEY_PICTURE_NAME, fileName); return builder.build(); } @Override public String getBodyContentType() { return mHttpEntity.getContentType().getValue(); } @Override public byte[] getBody() throws AuthFailureError { ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { mHttpEntity.writeTo(bos); } catch (IOException e) { VolleyLog.e("IOException writing to ByteArrayOutputStream"); } return bos.toByteArray(); } @Override protected Response parseNetworkResponse(NetworkResponse response) { return Response.success("Uploaded", getCacheEntry()); } @SuppressWarnings("unchecked") @Override protected void deliverResponse(String response) { mListener.onResponse(response); } private void logYazdir(String str) { if (Sabitler.LOG_KONTROL) { Log.d(TAG, str); } } } 

Y aquí este es el método para cargar imágenes.

  public void resimYukle(final String filePath) { logYazdir("KaydolActivity-uploadImage çağırıldı!"); logYazdir("\nfilePath : " + filePath); RequestQueue rq = Volley.newRequestQueue(this); PhotoMultipartRequest stringRequest = new PhotoMultipartRequest( Sabitler.URL_RESIM_YUKLE, filePath, new Response.Listener() { @Override public void onResponse(String response) { logYazdir("response : " + response); JSONObject veri_json; try { veri_json = new JSONObject(response); int success = 0; String message = ""; try { success = veri_json .getInt(Sabitler.SERVER_RESP_SUCCESS); message = veri_json .getString(Sabitler.SERVER_RESP_MESSAGE); Log.d(TAG, "success : " + success + "\nmessage : " + message); } catch (JSONException e) { e.printStackTrace(); } } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { logYazdir("Error [" + error + "]"); Toast.makeText(getBaseContext(), "Sunucuya bağlanılamadı!", Toast.LENGTH_LONG) .show(); } }) { @Override protected Map getParams() { Map params = new HashMap(); params.put("kullanici_resmi_dosya_adi", ""); return params; } }; rq.add(stringRequest); } 

¿Cómo vas a obtener filePath?

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { logYazdir("KaydolActivity-onActivityResult çağırıldı!"); if (requestCode == GALERIDEN_RESIM && resultCode == RESULT_OK && data != null) { logYazdir("KaydolActivity-GALERIDEN_RESIM çağırıldı!"); Uri selectedImage = data.getData(); String[] filePathColumn = { MediaStore.Images.Media.DATA }; Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null); cursor.moveToFirst(); int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); cursor.close(); Bitmap bmp = null; try { bmp = getBitmapFromUri(selectedImage); } catch (IOException e) { e.printStackTrace(); } kullanici_resmi_iview.setImageBitmap(bmp); resimYukle(picturePath); } super.onActivityResult(requestCode, resultCode, data); } 

Finalmente defina esto en su actividad,

 private int GALERIDEN_RESIM = 2; 

Parte importante, este es el código PHP para su servidor,

  750000) { $response["success"] = 0; $response["message"] = "Sorry, your file is too large."; echo json_encode($response); $uploadOk = 0; } // Allow certain file formats if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif" ) { $response["success"] = 0; $response["message"] = "Sorry, only JPG, JPEG, PNG & GIF files are allowed."; echo json_encode($response); $uploadOk = 0; } // Check if $uploadOk is set to 0 by an error if ($uploadOk == 0) { $response["success"] = 0; $response["message"] = "Sorry, your file was not uploaded."; echo json_encode($response); // if everything is ok, try to upload file } else { if (move_uploaded_file($_FILES["kullanici_resmi"]["tmp_name"], $target_file)) { $response["success"] = 0; $response["message"] = "The file ". basename( $_FILES["kullanici_resmi"]["name"]). " has been uploaded."; echo json_encode($response); } else { $response["success"] = 0; $response["message"] = "Sorry, there was an error uploading your file."; echo json_encode($response); } } ?> 

Debe asegurarse de enviar su archivo en este método,

 private HttpEntity buildMultipartEntity(File file) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); String fileName = file.getName(); logYazdir("fileName : " + fileName); FileBody fileBody = new FileBody(file); builder.addPart(KEY_PICTURE, fileBody); builder.addTextBody(KEY_PICTURE_NAME, fileName); return builder.build(); } 

y presta atención a esto,

 public static final String KEY_PICTURE = "kullanici_resmi"; 

kullanici_resmi

se usa en código PHP para indicar el archivo de imagen. Supongo que de esta manera, puedes enviar cualquier archivo. Perdón por mis pobres explicaciones, traté de explicar todo.