- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
通过混合使用相关答案中的代码,我成功地通过 multipart 进行了调用。但是,我无法使用正确的参数名称发送它。
请求必须如何(从 iOS 应用程序中获取):
我的请求看起来如何:
代码:
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/
我目前正在测试 Volley 库。但是当请求失败 (404) 时,它不会再次执行,或者至少没有错误。但是缺少数据。如果请求失败,这是重试请求的正确方法吗? 提前致谢 req.setRetryPolic
我是新来从事Volley和缓存工作的:P。尽管我已经看过许多与Volley进行图像缓存有关的文章和帖子,但是我仍然不清楚采用Volley进行图像缓存的最佳/首选方式。像磁盘缓存还是内存? Volley
我想使用 Volley 从我的 Android 应用发送请求。 我已经把它包含在 build.gradle 中了 dependencies { ... compile 'com.andr
我的目标是从另一个类调用 Volley,这是一种非常简洁、模块化的方式,即: VolleyListener newListener = new VolleyListener()
我的代码是: class MyService extends Service{ public void onCreate(){ new ImageLoader(mReque
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我需要帮助来解决 Volley 库错误。我已使用 nodejs api 向服务器发送一些凭据以进行用户注册。在成功的情况下,当我的所有凭据对于创建新用户帐户都是唯一的时,它会向我显示所有响应等的所有内
我正在尝试完善我的应用程序中的错误处理,但我找不到 Volley 触发某些错误的集中位置以及原因。例如,我想知道如果我的请求的状态代码是 500 或更大,它肯定会触发 ServerError,但我似乎
当我在调试器中运行该方法时,数据按预期显示,但是每当我尝试使用它执行任何操作时,parentObject 的值都会返回为 null。 我只是想从服务器获取响应并将其存储为 JSONObject 以便在
我正在使用 Android Volley 缓存请求,这在我使用 GET 时工作正常,但由于某些原因我改用 POST。现在我想用不同的 POST 数据缓存相同的 URL。 请求 1 -> URL1,PO
我的情况是使用 Android-volley至 POST我的 json 对象,我可以成功发布所有内容,我的数据在服务器中可见,但服务器响应为 String不像 json ,这就是出现错误的原因。 co
我正在使用 volley 从 REST api 解析电影详细信息,并将解析的数据保存在名为 detailsMovies 的对象数组列表中。但是我无法在 onResponse 方法之外访问 ArrayL
我想知道如何解决这个问题。已完成代码的研究和替换,但问题仍然存在。 这是我使用 volley 的代码。 private void Regist(){ loading.setVisibility
如何创建一个单独的类,在其中定义所有关于 volley在另一个 Activity 中,我们直接传递 URL、CONTEXT 和 Get Response... 最佳答案 首先在Activity中创建回
我正在使用 volley 库并以 XML 格式获取响应。我想知道我们如何使用/volley 库解析响应。谢谢。 最佳答案 StringRequest req = new StringReque
当我在android studio中搜索 Volley 时,同时获取com.mcxiaoke.volley:library:1.0.19和com.mcxiaoke.volley:library-aar
我是 volley 和 android 的新手,我已经用 gradle 安装了 volley 并做了与官方教程相同的操作。但是没有响应,这意味着 Errorlistener 和 Responselis
当我在 Volley 中发出请求时,我收到 com.android.volley.ServerError 和响应代码 400。 我正在做这样的事情(通用示例代码): final String para
我引用了http://www.androidhive.info/2016/02/android-push-notifications-using-gcm-php-mysql-realtime-chat
当我将以下行添加到依赖项的 build.gradle 行时,Android Studio 显示此错误消息:compile 'com.android.volley:volley:1.0.0' apply
我是一名优秀的程序员,十分优秀!