Ce n'est pas vraiment une question, cependant, je voudrais partager une partie de mon code de travail ici pour votre référence lorsque vous en avez besoin.
Comme nous le savons, il HttpEntity
est obsolète d'API22 et entièrement supprimé depuis API23. Pour le moment, nous ne pouvons plus accéder à HttpEntity Reference sur Android Developer (404). Ainsi, voici mon exemple de code de travail pour POST Multipart Request avec Volley et sans HttpEntity . Cela fonctionne, testé avec Asp.Net Web API
. Bien sûr, le code n'est peut-être qu'un exemple de base qui publie deux fichiers dessinables existants, n'est pas non plus la meilleure solution dans tous les cas et n'est pas un bon réglage.
MultipartActivity.java:
package com.example.multipartvolley;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.android.volley.NetworkResponse;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
public class MultipartActivity extends Activity {
private final Context context = this;
private final String twoHyphens = "--";
private final String lineEnd = "\r\n";
private final String boundary = "apiclient-" + System.currentTimeMillis();
private final String mimeType = "multipart/form-data;boundary=" + boundary;
private byte[] multipartBody;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_multipart);
byte[] fileData1 = getFileDataFromDrawable(context, R.drawable.ic_action_android);
byte[] fileData2 = getFileDataFromDrawable(context, R.drawable.ic_action_book);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
try {
// the first file
buildPart(dos, fileData1, "ic_action_android.png");
// the second file
buildPart(dos, fileData2, "ic_action_book.png");
// send multipart form data necesssary after file data
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
// pass to multipart body
multipartBody = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
String url = "http://192.168.1.100/api/postfile";
MultipartRequest multipartRequest = new MultipartRequest(url, null, mimeType, multipartBody, new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
Toast.makeText(context, "Upload successfully!", Toast.LENGTH_SHORT).show();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context, "Upload failed!\r\n" + error.toString(), Toast.LENGTH_SHORT).show();
}
});
VolleySingleton.getInstance(context).addToRequestQueue(multipartRequest);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_multipart, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void buildPart(DataOutputStream dataOutputStream, byte[] fileData, String fileName) throws IOException {
dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\"; filename=\""
+ fileName + "\"" + lineEnd);
dataOutputStream.writeBytes(lineEnd);
ByteArrayInputStream fileInputStream = new ByteArrayInputStream(fileData);
int bytesAvailable = fileInputStream.available();
int maxBufferSize = 1024 * 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
byte[] buffer = new byte[bufferSize];
// read file and write it into form...
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0) {
dataOutputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
dataOutputStream.writeBytes(lineEnd);
}
private byte[] getFileDataFromDrawable(Context context, int id) {
Drawable drawable = ContextCompat.getDrawable(context, id);
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 0, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}
}
MultipartRequest.java:
package com.example.multipartvolley;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import java.util.Map;
class MultipartRequest extends Request<NetworkResponse> {
private final Response.Listener<NetworkResponse> mListener;
private final Response.ErrorListener mErrorListener;
private final Map<String, String> mHeaders;
private final String mMimeType;
private final byte[] mMultipartBody;
public MultipartRequest(String url, Map<String, String> headers, String mimeType, byte[] multipartBody, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
super(Method.POST, url, errorListener);
this.mListener = listener;
this.mErrorListener = errorListener;
this.mHeaders = headers;
this.mMimeType = mimeType;
this.mMultipartBody = multipartBody;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return (mHeaders != null) ? mHeaders : super.getHeaders();
}
@Override
public String getBodyContentType() {
return mMimeType;
}
@Override
public byte[] getBody() throws AuthFailureError {
return mMultipartBody;
}
@Override
protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
try {
return Response.success(
response,
HttpHeaderParser.parseCacheHeaders(response));
} catch (Exception e) {
return Response.error(new ParseError(e));
}
}
@Override
protected void deliverResponse(NetworkResponse response) {
mListener.onResponse(response);
}
@Override
public void deliverError(VolleyError error) {
mErrorListener.onErrorResponse(error);
}
}
METTRE À JOUR:
Pour la partie texte, veuillez vous référer à la réponse de @ Oscar ci-dessous.
Réponses:
Je réécris votre code @RacZo et @BNK plus modulable et facile à utiliser comme
Vérifiez plein de code
VolleyMultipartRequest
à mon sens .la source
Je veux juste ajouter à la réponse. J'essayais de comprendre comment ajouter des champs de texte au corps et j'ai créé la fonction suivante pour le faire:
Cela fonctionne plutôt bien.
la source
Pour ceux qui ont du mal à envoyer les paramètres utf-8 et qui n'ont toujours pas de chance, le problème que j'ai eu était dans le dataOutputStream, et changez le code de @RacZo en code ci-dessous:
la source
Voici une version Kotlin d'une classe permettant la requête en plusieurs parties avec Volley 1.1.1.
Il est principalement basé sur la solution de @ BNK mais légèrement simplifié. Je n'ai remarqué aucun problème de performances particulier. J'ai téléchargé une photo de 5 Mo en 3 secondes environ.
la source
J'ai trouvé un wrapper de la bibliothèque de volée originale qui est plus facile à intégrer pour les demandes en plusieurs parties. Il prend également en charge le téléchargement des données en plusieurs parties avec d'autres paramètres de demande. Par conséquent, je partage mon code pour les futurs développeurs qui pourraient rencontrer le problème que j'avais (c'est-à-dire télécharger des données en plusieurs parties en utilisant volley avec d'autres paramètres).
Ajoutez la bibliothèque suivante dans le
build.gradle
fichier.Veuillez noter que j'ai supprimé la bibliothèque de volée d'origine de mon
build.gradle
et utilisé la bibliothèque ci-dessus à la place, qui peut gérer à la fois les demandes en plusieurs parties et normales ayant une technique d'intégration similaire.Ensuite, je devais juste écrire la classe suivante qui gère l'opération de requête POST.
Exécutez maintenant la tâche comme suit.
Vous pouvez télécharger un fichier à la fois en utilisant cette bibliothèque. Cependant, je pourrais réussir à télécharger plusieurs fichiers, simplement en lançant plusieurs tâches.
J'espère que cela pourra aider!
la source