gpt4 book ai didi

java - Android Volley 多部分参数名称

转载 作者:行者123 更新时间:2023-11-29 09:28:35 26 4
gpt4 key购买 nike

通过混合使用相关答案中的代码,我成功地通过 multipart 进行了调用。但是,我无法使用正确的参数名称发送它。

请求必须如何(从 iOS 应用程序中获取):

enter image description here

enter image description here

我的请求看起来如何:

enter image description here

enter image description here

代码:

MultipartRequest 应该是一个基本的多部分请求。

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.util.Log;

import com.android.volley.Request;
import com.android.volley.Response;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;

import com.android.volley.AuthFailureError;
import com.android.volley.toolbox.StringRequest;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class MultipartRequest extends StringRequest {
private final int maxImageWidth = 200;
private final int maxImageHeight = 200;

static String mimeType;
private final File file;
DataOutputStream dos = null;
String lineEnd = "\r\n";
static String boundary = "apiclient-" + System.currentTimeMillis();
String twoHyphens = "--";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 124 * 124;

public static MultipartRequest newInstance(final PlayEarnAPIImpl.OnPlayEarnAPIResponse listener, File file, Response.Listener<String> responseListener, Response.ErrorListener errorListener, String serviceURL) {
mimeType = "multipart/form-data;boundary=" + boundary;
return new MultipartRequest(Request.Method.PUT, serviceURL, responseListener, errorListener, file, serviceURL);
}

public MultipartRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener, File file, String serviceURL) {
super(method, url, listener, errorListener);
this.file = file;
}

private byte[] decodeFile(File file) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
options.inSampleSize = calculateInSampleSize(options, 400, 400);
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
}

public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;

if (height > reqHeight || width > reqWidth) {

final int halfHeight = height / 2;
final int halfWidth = width / 2;

// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}

return inSampleSize;
}

//solution 2
private byte[] shrinkImage(File file) {
try {
int inWidth = 0;
int inHeight = 0;

InputStream in = new FileInputStream(file.getAbsolutePath());

// decode image size (decode metadata only, not the whole image)
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(in, null, options);
in.close();
in = null;

// save width and height
inWidth = options.outWidth;
inHeight = options.outHeight;

// decode full image pre-resized
in = new FileInputStream(file.getAbsolutePath());
options = new BitmapFactory.Options();
// calc rought re-size (this is no exact resize)
options.inSampleSize = Math.max(inWidth / maxImageWidth, inHeight / maxImageHeight);
// decode full image
Bitmap roughBitmap = BitmapFactory.decodeStream(in, null, options);

// calc exact destination size
Matrix m = new Matrix();
RectF inRect = new RectF(0, 0, roughBitmap.getWidth(), roughBitmap.getHeight());
RectF outRect = new RectF(0, 0, maxImageWidth, maxImageHeight);
m.setRectToRect(inRect, outRect, Matrix.ScaleToFit.CENTER);
float[] values = new float[9];
m.getValues(values);

// resize bitmap
Bitmap resizedBitmap = Bitmap.createScaledBitmap(roughBitmap, (int) (roughBitmap.getWidth() * values[0]), (int) (roughBitmap.getHeight() * values[4]), true);

// save image

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
resizedBitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
return byteArrayOutputStream.toByteArray();
} catch (IOException e) {
Log.e("Image", e.getMessage(), e);
}
return null;
}

@Override
public String getBodyContentType() {
return mimeType;
}

@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
dos = new DataOutputStream(bos);
byte[] bitmapData = null;
try {
//dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(" ------------------12345");
dos.writeBytes(lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"picture\"; filename=\"file.png\"");
dos.writeBytes(lineEnd);
dos.writeBytes("Content-Type: image/png");
//dos.writeBytes("Content-Disposition: form-data; name=\"picture\";filename=\""
// + file.getName() + "\"" + lineEnd);
dos.writeBytes(lineEnd);
bitmapData = shrinkImage(this.file);
ByteArrayInputStream fileInputStream = new ByteArrayInputStream(bitmapData);
bytesAvailable = fileInputStream.available();

bufferSize = Math.min(bytesAvailable, maxBufferSize);
Log.d("MultipartRequest", "bufferSize:" + bufferSize);
buffer = new byte[bufferSize];

// read file and write it into form...
bytesRead = fileInputStream.read(buffer, 0, bufferSize);

while (bytesRead > 0) {
dos.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}

// send multipart form data necesssary after file data...
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

return bos.toByteArray();

} catch (IOException e) {
e.printStackTrace();
}
return bitmapData;
}

这是我正在使用的请求:

import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.google.gson.Gson;

import java.io.File;
import java.util.Map;

public class ChangeProfileImageRequest extends MultipartRequest {
private static final String UPDATE_PATH = "users/update";
String serviceURL = APIImpl.API_URL + UPDATE_PATH;

public static ChangeProfileImageRequest newInstance(final APIImpl.OnAPIResponse listener, File file) {
String serviceURL = APIImpl.API_URL + UPDATE_PATH;

return new ChangeProfileImageRequest(Request.Method.PUT, serviceURL, new ResponseListener(listener), new ErrorListener(listener), file, serviceURL);
}

public ChangeProfileImageRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener, File file, String serviceURL) {
super(method, url, listener, errorListener, file, serviceURL);
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new APIImpl().getTokenHeader();
//headers.put("Accept", "*/*");
headers.put("Content-Type", "multipart/form-data;boundary=----------------12345");
AppController.getInstance().addSessionCookie(headers);
return headers;
}

所以我猜这与“无法解码多部分正文”的屏幕截图有关,但我不知 Prop 体问题是什么。同样从服务器端未收到图片参数。

最佳答案

我设法让它工作,将 com.squareup.okhttp 添加到 gradle,并更改 this class一点点。

基本多部分请求:

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.RetryPolicy;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;

import com.squareup.okhttp.Headers;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.MultipartBuilder;
import com.squareup.okhttp.RequestBody;

import android.util.Log;

import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import okio.Buffer;

/**
* Multipart request for Google's Volley using Square's OkHttp.
*
* @author Hussain Al-Derry
* @version 1.0
*/
public class VolleyMultipartRequest extends Request<String> {

/* Used for debugging */
private static final String TAG = VolleyMultipartRequest.class.getSimpleName();

/* MediaTypes */
public static final MediaType MEDIA_TYPE_JPEG = MediaType.parse("image/jpeg");
public static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
public static final MediaType MEDIA_TYPE_TEXT_PLAIN = MediaType.parse("text/plain");

private MultipartBuilder mBuilder = new MultipartBuilder();
private final Response.Listener<String> mListener;
private RequestBody mRequestBody;

public VolleyMultipartRequest(int method, String url,
Response.ErrorListener errorListener,
Response.Listener<String> listener) {
super(method, url, errorListener);
mListener = listener;
mBuilder.type(MultipartBuilder.FORM);
}

/**
* Adds a collection of string values to the request.
*
* @param mParams {@link HashMap} collection of values to be added to the request.
*/
public void addStringParams(HashMap<String, String> mParams) {
for (Map.Entry<String, String> entry : mParams.entrySet()) {
mBuilder.addPart(
Headers.of("Content-Disposition", "form-data; name=\"" + entry.getKey() + "\""),
RequestBody.create(MEDIA_TYPE_TEXT_PLAIN, entry.getValue()));
}
}

/**
* Adds a single value to the request.
*
* @param key String - the field name.
* @param value String - the field's value.
*/
public void addStringParam(String key, String value) {
mBuilder.addPart(
Headers.of("Content-Disposition", "form-data; name=\"" + key + "\""),
RequestBody.create(MEDIA_TYPE_TEXT_PLAIN, value));
}

/**
* Adds a binary attachment to the request.
*
* @param content_type {@link MediaType} - the type of the attachment.
* @param fileName String - the attachment field name.
* @param value {@link File} - the file to be attached.
*/
public void addAttachment(MediaType content_type, String paramName, String fileName, File value) {
mBuilder.addFormDataPart(paramName, fileName, RequestBody.create(content_type, value));
}

/**
* Builds the request.
* Must be called before adding the request to the Volley request queue.
*/
public void buildRequest() {
mRequestBody = mBuilder.build();
}

@Override
public String getBodyContentType() {
return mRequestBody.contentType().toString();
}

@Override
public byte[] getBody() throws AuthFailureError {
Buffer buffer = new Buffer();
try {
mRequestBody.writeTo(buffer);
} catch (IOException e) {
Log.e(TAG, e.toString());
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return buffer.readByteArray();
}

@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}

@Override
public Request<?> setRetryPolicy(RetryPolicy retryPolicy) {
return super.setRetryPolicy(retryPolicy);
}

@Override
protected void deliverResponse(String response) {
if (mListener != null) {
mListener.onResponse(response);
}
}
}

并根据我的特定要求对其进行子类化:

public class ChangeProfileImageRequest extends VolleyMultipartRequest {
private static final String UPDATE_PATH = "users/update";

public static ChangeProfileImageRequest newInstance(final APIImpl.OnAPIResponse listener, File file) {
String serviceURL = APIImpl.API_URL + UPDATE_PATH;

//return new ChangeProfileImageRequest(Request.Method.PUT, serviceURL, new ResponseListener(listener), new ErrorListener(listener), file, serviceURL);
ChangeProfileImageRequest request = new ChangeProfileImageRequest(Method.PUT, serviceURL, new ErrorListener(listener), new ResponseListener(listener));
request.addAttachment(MEDIA_TYPE_PNG, "picture", "file.png", file);

return request;
}

public ChangeProfileImageRequest(int method, String url, Response.ErrorListener errorListener, Response.Listener<String> listener) {
super(method, url, errorListener, listener);
}

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new APIImpl().getTokenHeader();
headers.put("Accept", "*/*");
AppController.getInstance().addSessionCookie(headers);
return headers;
}

//ErrorListener and ResponseListener classes

并将其添加到 Volley 中:

public void updateProfileImage(APIImpl.OnAPIResponse listener, File image) {
ChangeProfileImageRequest request = ChangeProfileImageRequest.newInstance(listener, image);
request.buildRequest();
// Access the RequestQueue through your singleton class.
request.setRetryPolicy(new DefaultRetryPolicy(
0,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
VolleySingleton.getInstance().addToRequestQueue(request);
}

不过,我会接受一个只使用 Volley 的答案。我想仅仅因为一个请求不起作用就使用 Volley 和 OkHttp 并不理想。

关于java - Android Volley 多部分参数名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36183571/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com