有没有人能够在安卓系统中用Volley完成发送 "multipart/form-data "POST?我没有成功地使用POST请求向我们的服务器上传图像/png
,我很好奇是否有人能做到。
我相信默认的方法是在Request.java
类中覆盖public byte[] getPostBody()
,并在那里附加File
,为边界设置一个空白Header键。然而,为Map<String, String> postParams
将我的文件转换为String
,然后再对其进行编码,这似乎很笨拙,并不优雅。 而且我的尝试也不成功。这确实是阻碍我们转向这个库的唯一原因。
无论如何,我们非常感谢所有的想法和答案。谢谢你的帮助。
我可能错了,但我认为你需要实现你自己的com.android.volley.toolbox.HttpStack
,因为默认的(HurlStack
如果版本> Gingerbread或HttpClientStack
)不处理multipart/form-data
。
编辑:
我确实错了。我能够像这样在Request中使用MultipartEntity
来做:
public class MultipartRequest extends Request<String> {
private MultipartEntity entity = new MultipartEntity();
private static final String FILE_PART_NAME = "file";
private static final String STRING_PART_NAME = "text";
private final Response.Listener<String> mListener;
private final File mFilePart;
private final String mStringPart;
public MultipartRequest(String url, Response.ErrorListener errorListener, Response.Listener<String> listener, File file, String stringPart)
{
super(Method.POST, url, errorListener);
mListener = listener;
mFilePart = file;
mStringPart = stringPart;
buildMultipartEntity();
}
private void buildMultipartEntity()
{
entity.addPart(FILE_PART_NAME, new FileBody(mFilePart));
try
{
entity.addPart(STRING_PART_NAME, new StringBody(mStringPart));
}
catch (UnsupportedEncodingException e)
{
VolleyLog.e("UnsupportedEncodingException");
}
}
@Override
public String getBodyContentType()
{
return entity.getContentType().getValue();
}
@Override
public byte[] getBody() throws AuthFailureError
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try
{
entity.writeTo(bos);
}
catch (IOException e)
{
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response)
{
return Response.success("Uploaded", getCacheEntry());
}
@Override
protected void deliverResponse(String response)
{
mListener.onResponse(response);
}
}
这是很原始的,但我用一张图片和一个简单的字符串试了一下,它是有效的。响应是一个占位符,在这种情况下,返回一个响应字符串没有什么意义。我在使用apache httpmime使用MultipartEntity时遇到了问题,所以我使用了这个https://code.google.com/p/httpclientandroidlib/,不知道是否有更好的方法。 希望能有所帮助。
编辑
你可以不使用httpclientandroidlib而使用httpspmime,唯一的依赖是httpcore。
正如在I/O的演讲中提到的(大约4:05),Volley "对于大的有效载荷来说是很糟糕的" 。根据我的理解,这意味着不要用Volley来接收/发送(大)文件。看一下代码,似乎它甚至没有被设计来处理多部分的表单数据(例如,Request.java的getBodyContentType()有硬编码的"application/x-www-form-urlencoded";HttpClientStack::createHttpRequest()只能处理byte[],等等)。也许你能够创建能够处理多部分的实现,但如果我是你,我将直接使用HttpClient和MultipartEntity,比如:
HttpPost req = new HttpPost(composeTargetUrl());
MultipartEntity entity = new MultipartEntity();
entity.addPart(POST_IMAGE_VAR_NAME, new FileBody(toUpload));
try {
entity.addPart(POST_SESSION_VAR_NAME, new StringBody(uploadSessionId));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
req.setEntity(entity);
你可能需要较新的HttpClient(即不是内置的),或者甚至更好,用较新的HttpClient使用Volley
另一种解决方案,非常轻,有效载荷大,性能高:
Android异步Http客户端库: http://loopj.com/android-async-http/
private static AsyncHttpClient client = new AsyncHttpClient();
private void uploadFileExecute(File file) {
RequestParams params = new RequestParams();
try { params.put("photo", file); } catch (FileNotFoundException e) {}
client.post(getUrl(), params,
new AsyncHttpResponseHandler() {
public void onSuccess(String result) {
Log.d(TAG,"uploadFile response: "+result);
};
public void onFailure(Throwable arg0, String errorMsg) {
Log.d(TAG,"uploadFile ERROR!");
};
}
);
}