Dies ist nicht wirklich eine Frage, ich möchte jedoch einen Teil meines Arbeitscodes hier als Referenz für Sie freigeben, wenn Sie dies benötigen.
Wie wir wissen, HttpEntity
ist das von API22 veraltet und seit API23 vollständig entfernt. Derzeit können wir auf Android Developer (404) nicht mehr auf HttpEntity Reference zugreifen . Das Folgende ist mein Arbeitsbeispielcode für POST Multipart Request mit Volley und ohne HttpEntity . Es funktioniert, getestet mit Asp.Net Web API
. Natürlich ist der Code vielleicht nur ein grundlegendes Beispiel, in dem zwei vorhandene zeichnbare Dateien veröffentlicht werden. Er ist auch nicht in allen Fällen die beste Lösung und keine gute Optimierung.
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);
}
}
AKTUALISIEREN:
Für den Textteil lesen Sie bitte die Antwort von @ Oscar unten.
Antworten:
Ich schreibe Ihren Code @RacZo und @BNK modularer und benutzerfreundlicher um
Überprüfen Sie den Code
VolleyMultipartRequest
in meinem Kern .quelle
Ich möchte nur die Antwort ergänzen. Ich habe versucht herauszufinden, wie Textfelder an den Körper angehängt werden, und die folgende Funktion erstellt, um dies zu tun:
Es funktioniert ziemlich gut.
quelle
Für diejenigen, die Schwierigkeiten haben, utf-8-Parameter zu senden und immer noch kein Glück haben, war das Problem, das ich hatte, im dataOutputStream und ändern Sie den Code von @RacZo in den folgenden Code:
quelle
Hier ist eine Kotlin-Version einer Klasse, die eine mehrteilige Anforderung mit Volley 1.1.1 ermöglicht.
Es basiert hauptsächlich auf der Lösung von @ BNK, ist jedoch leicht vereinfacht. Ich habe kein bestimmtes Leistungsproblem festgestellt. Ich habe in ca. 3 Sekunden ein 5-MB-Bild hochgeladen.
quelle
Ich habe einen Wrapper der ursprünglichen Volley-Bibliothek gefunden, der für mehrteilige Anfragen einfacher zu integrieren ist. Es unterstützt auch das Hochladen der mehrteiligen Daten zusammen mit anderen Anforderungsparametern. Daher teile ich meinen Code für zukünftige Entwickler, die möglicherweise auf das Problem stoßen, das ich hatte (dh das Hochladen mehrteiliger Daten mit Volley zusammen mit einigen anderen Parametern).
Fügen Sie der
build.gradle
Datei die folgende Bibliothek hinzu .Bitte beachten Sie, dass ich die ursprüngliche Volley-Bibliothek aus meiner entfernt
build.gradle
und stattdessen die obige Bibliothek verwendet habe, die sowohl mehrteilige als auch normale Anforderungen mit ähnlicher Integrationstechnik verarbeiten kann.Dann musste ich nur noch die folgende Klasse schreiben, die die POST-Anforderungsoperation behandelt.
Führen Sie nun die Aufgabe wie folgt aus.
Mit dieser Bibliothek können Sie jeweils eine Datei hochladen. Es könnte mir jedoch gelingen, mehrere Dateien hochzuladen, indem ich einfach mehrere Aufgaben initiiere.
Hoffentlich hilft das!
quelle