通过故障凌空发送分段文件与边界 [英] Trouble Sending Multipart File with Boundary via Volley
问题描述
我有一个客户HTTP调用工作使用标准的Apache类,但我想创建一个自定义的凌空类来处理这个问题。这里是code标准的呼叫:
HttpURLConnection的康恩=(HttpURLConnection类)新的URL(strUrl).openConnection();
conn.setDoOutput(真正的);
conn.setDoInput(真正的);
conn.setConnectTimeout(30000);
conn.setUseCaches(真正的);
conn.setRequestMethod(POST);
conn.setRequestProperty(授权,令牌+ m_apiKey);
conn.setRequestProperty(接受,text / plain的,应用/ JSON);
conn.setRequestProperty(连接,保持活动);
conn.setRequestProperty(内容类型,多部分/格式数据;边界=+ strBoundary);
conn.connect();
// ****开始内容包装:
DataOutputStream类要求=新DataOutputStream类(conn.getOutputStream());
request.writeBytes(\ r \ N--+ strBoundary +\ r \ N);
request.writeBytes(内容处置:表格数据;名称= \+ attachmentName +\;文件名= \+映像文件名称+\+\ r \ N);
request.writeBytes(内容类型:image / JPEG+\ r \ N);
request.writeBytes(\ r \ N);
request.write(baos.toByteArray());
// ****结束内容包装:
request.writeBytes(\ r \ N - + strBoundary + - \ r \ N);
//刷新输出缓冲:
request.flush(); request.close();
不知道如何做休息,但是这是我有不工作的抽射高出。我以前而不是已经做了多部与边界和这个奇怪的格式。
公共类ImageMultiRequest扩展StringRequest { 最后弦乐边界=东西; 最后弦乐CRLF =\ r \ N的; 最后弦乐twoHyphens = - ;
私人最终MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
私人Response.Listener<字符串> mListener = NULL;
私人Response.ErrorListener mEListener;
//
私人最终文件mFilePart;
私人地图<字符串,字符串>参数;
私人地图<字符串,字符串>头;
MultipartEntity实体=新MultipartEntity();
保护字符串apiKey;
ByteArrayOutputStream BOS;
公共ImageMultiRequest(字符串apiKey,字符串URL,收听LT;字符串> rListener,ErrorListener eListener,档案文件){
超(Method.POST,网址,rListener,eListener);
setShouldCache(假);
this.apiKey = apiKey;
this.bos = BOS;
mListener = rListener;
mEListener = eListener;
mFilePart =文件;
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(边界);
buildMultipartEntity();
}
@覆盖
公共字符串getBodyContentType(){
返回的multipart / form-data的;边界=+边界+;字符集= UTF-8;
}
/ **
*覆盖的基类,添加接受:应用/ JSON头
* /
@覆盖
公共地图<字符串,字符串> getHeaders()抛出AuthFailureError {
地图<字符串,字符串>标题= super.getHeaders();
如果(标题== NULL || headers.equals(Collections.emptyMap())){
标题=新的HashMap<字符串,字符串>();
}
headers.put(内容类型,多部分/格式数据;边界=+边界+;字符集= UTF-8);
headers.put(连接,保持活动);
headers.put(接受,text / plain的,应用/ JSON);
headers.put(授权,令牌+ apiKey);
返回头;
}
@覆盖
公共字节[] getBody()抛出AuthFailureError {
buildMultipartEntity();
ByteArrayOutputStream BOS =新ByteArrayOutputStream();
尝试 {
。entityBuilder.build()的writeTo(BOS);
}赶上(IOException异常E){
VolleyLog.e(IOException异常写入ByteArrayOutputStream);
}
返回bos.toByteArray();
}
私人无效buildMultipartEntity(){
ByteArrayOutputStream BOS =新ByteArrayOutputStream();
entityBuilder.addPart(内容类型:image / JPEG+ CRLF + CRLF,新ByteArrayBody(bos.toByteArray(),汽车));
}
}
=============================================== ==
解决方案基于以下
答案下面是我想出了工作,这和其他可能的问题嵌入式多部分文件中的内容主体
包com.cars.android.common.volley;
进口com.android.volley.AuthFailureError;
进口com.android.volley.Response;
进口com.android.volley.Response.ErrorListener;
进口com.android.volley.Response.Listener;
进口com.android.volley.VolleyLog;
进口com.android.volley.toolbox.StringRequest;
进口org.apache.http.HttpEntity;
进口org.apache.http.entity.ContentType;
进口org.apache.http.entity.mime.HttpMultipartMode;
进口org.apache.http.entity.mime.MultipartEntity;
进口org.apache.http.entity.mime.MultipartEntityBuilder;
进口java.io.ByteArrayOutputStream中;
进口的java.io.File;
进口java.io.IOException异常;
进口java.util.Collections中;
进口的java.util.HashMap;
进口的java.util.Map;
公共类ImageMultiRequest扩展StringRequest {
最后弦乐边界=myboundary;
私人最终MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
HttpEntity实体=新MultipartEntity();
私人Response.Listener<字符串> mListener = NULL;
私人Response.ErrorListener mEListener;
//
私人最终文件mFilePart;
保护字符串apiKey;
公共ImageMultiRequest(字符串apiKey,字符串URL,收听LT;字符串> rListener,ErrorListener eListener,档案文件){
超(Method.POST,网址,rListener,eListener);
setShouldCache(假);
this.apiKey = apiKey;
mListener = rListener;
mEListener = eListener;
mFilePart =文件;
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(边界);
的ContentType的contentType = ContentType.create(图像/ PNG);
entityBuilder.addBinaryBody(文件,文件的contentType,汽车);
实体= entityBuilder.build();
}
@覆盖
公共字符串getBodyContentType(){
返回entity.getContentType()的getValue()。
}
/ **
*覆盖的基类,添加接受:应用/ JSON头
* /
@覆盖
公共地图<字符串,字符串> getHeaders()抛出AuthFailureError {
地图<字符串,字符串>标题= super.getHeaders();
如果(标题== NULL || headers.equals(Collections.emptyMap())){
标题=新的HashMap<字符串,字符串>();
}
headers.put(内容类型,多部分/格式数据;边界=+边界+;字符集= UTF-8);
headers.put(连接,保持活动);
headers.put(接受,text / plain的,应用/ JSON);
headers.put(授权,令牌+ apiKey);
返回头;
}
@覆盖
公共字节[] getBody()抛出AuthFailureError {
ByteArrayOutputStream BOS =新ByteArrayOutputStream();
尝试 {
entity.writeTo(BOS);
}赶上(IOException异常E){
VolleyLog.e(IOException异常写入ByteArrayOutputStream);
}
返回bos.toByteArray();
}
}
这是我的工作示例code(仅适用于小尺寸的文件测试):
公共类FileUploadActivity延伸活动{
私人最终上下文mContext =这一点;
HttpEntity httpEntity;
@覆盖
保护无效的onCreate(包savedInstanceState){
super.onCreate(savedInstanceState);
的setContentView(R.layout.activity_file_upload);
可绘制绘制= getResources()getDrawable(R.drawable.ic_action_home)。
如果(绘制!= NULL){
点阵位图=((BitmapDrawable)绘制).getBitmap();
ByteArrayOutputStream流=新ByteArrayOutputStream();
bitmap.com preSS(Bitmap.Com pressFormat.PNG,100,流);
最后一个字节[]的BitmapData = stream.toByteArray();
字符串URL =http://10.0.2.2/api/fileupload;
MultipartEntityBuilder建设者= MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//添加二元体
如果(的BitmapData!= NULL){
的ContentType的contentType = ContentType.create(图像/ PNG);
字符串文件名=ic_action_home.png;
builder.addBinaryBody(文件的BitmapData,contentType中,文件名);
httpEntity = builder.build();
MyRequest myRequest =新MyRequest(Request.Method.POST,网址,新Response.Listener< NetworkResponse>(){
@覆盖
公共无效onResponse(NetworkResponse响应){
尝试 {
字符串jsonString =新的String(response.data,
HttpHeaderParser.parseCharset(response.headers));
Toast.makeText(mContext,jsonString,Toast.LENGTH_SHORT).show();
}赶上(例外五){
e.printStackTrace();
}
}
},新Response.ErrorListener(){
@覆盖
公共无效onErrorResponse(VolleyError错误){
Toast.makeText(mContext,error.toString(),Toast.LENGTH_SHORT).show();
}
}){
@覆盖
公共字符串getBodyContentType(){
返回httpEntity.getContentType()的getValue()。
}
@覆盖
公共字节[] getBody()抛出AuthFailureError {
ByteArrayOutputStream BOS =新ByteArrayOutputStream();
尝试 {
httpEntity.writeTo(BOS);
}赶上(IOException异常E){
VolleyLog.e(IOException异常写入ByteArrayOutputStream);
}
返回bos.toByteArray();
}
};
MySingleton.getInstance(本).addToRequestQueue(myRequest);
}
}
}
...
}
公共类MyRequest扩展请求< NetworkResponse>
I have a customers HTTP call working using the standard apache classes but I am trying to create a custom Volley class to handle this. Here is the code for standard call:
HttpURLConnection conn = (HttpURLConnection) new URL(strUrl).openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setConnectTimeout(30000);
conn.setUseCaches(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Token " + m_apiKey);
conn.setRequestProperty("Accept", "text/plain , application/json");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + strBoundary);
conn.connect();
// **** Start content wrapper:
DataOutputStream request = new DataOutputStream(conn.getOutputStream());
request.writeBytes("\r\n--" + strBoundary + "\r\n");
request.writeBytes("Content-Disposition: form-data; name=\"" + attachmentName + "\";filename=\"" + imageFileName + "\"" + "\r\n");
request.writeBytes("Content-Type: image/jpeg " + "\r\n");
request.writeBytes("\r\n");
request.write(baos.toByteArray());
// **** End content wrapper:
request.writeBytes("\r\n--"+ strBoundary + "--\r\n");
// Flush output buffer:
request.flush();request.close();
Not sure how to do the rest but this is what I have for the Volley that is not working. I've done Multipart before but not with boundary and in this weird format.
public class ImageMultiRequest extends StringRequest { final String BOUNDARY = "something"; final String crlf = "\r\n"; final String twoHyphens = "--";
private final MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
private Response.Listener<String> mListener = null;
private Response.ErrorListener mEListener;
//
private final File mFilePart;
private Map<String, String> parameters;
private Map<String, String> header;
MultipartEntity entity = new MultipartEntity();
protected String apiKey;
ByteArrayOutputStream bos;
public ImageMultiRequest(String apiKey, String url, Listener<String> rListener, ErrorListener eListener, File file) {
super(Method.POST, url, rListener, eListener);
setShouldCache(false);
this.apiKey = apiKey;
this.bos = bos;
mListener = rListener;
mEListener = eListener;
mFilePart = file;
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(BOUNDARY);
buildMultipartEntity();
}
@Override
public String getBodyContentType() {
return "multipart/form-data; boundary=" + BOUNDARY + "; charset=utf-8";
}
/**
* Overrides the base class to add the Accept: application/json header
*/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
headers.put("Content-Type", "multipart/form-data;boundary=" + BOUNDARY+ "; charset=utf-8");
headers.put("Connection", "Keep-Alive");
headers.put("Accept", "text/plain , application/json");
headers.put("Authorization", "Token " + apiKey);
return headers;
}
@Override
public byte[] getBody() throws AuthFailureError {
buildMultipartEntity();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
entityBuilder.build().writeTo(bos);
} catch (IOException e) {
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
private void buildMultipartEntity() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
entityBuilder.addPart("Content-Type: image/jpeg " + crlf + crlf, new ByteArrayBody(bos.toByteArray(), "car"));
}
}
=================================================
SOLUTION Based on the answer below
Here is what I came up with that worked for this and possibly other problems with multipart file embedded the Content Body
package com.cars.android.common.volley;
import com.android.volley.AuthFailureError;
import com.android.volley.Response;
import com.android.volley.Response.ErrorListener;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.StringRequest;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class ImageMultiRequest extends StringRequest {
final String BOUNDARY = "myboundary";
private final MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
HttpEntity entity = new MultipartEntity();
private Response.Listener<String> mListener = null;
private Response.ErrorListener mEListener;
//
private final File mFilePart;
protected String apiKey;
public ImageMultiRequest(String apiKey, String url, Listener<String> rListener, ErrorListener eListener, File file) {
super(Method.POST, url, rListener, eListener);
setShouldCache(false);
this.apiKey = apiKey;
mListener = rListener;
mEListener = eListener;
mFilePart = file;
entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entityBuilder.setBoundary(BOUNDARY);
ContentType contentType = ContentType.create("image/png");
entityBuilder.addBinaryBody("file", file, contentType, "car");
entity = entityBuilder.build();
}
@Override
public String getBodyContentType() {
return entity.getContentType().getValue();
}
/**
* Overrides the base class to add the Accept: application/json header
*/
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = super.getHeaders();
if (headers == null || headers.equals(Collections.emptyMap())) {
headers = new HashMap<String, String>();
}
headers.put("Content-Type", "multipart/form-data;boundary=" + BOUNDARY+ "; charset=utf-8");
headers.put("Connection", "Keep-Alive");
headers.put("Accept", "text/plain , application/json");
headers.put("Authorization", "Token " + apiKey);
return headers;
}
@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();
}
}
This is my working sample code (only tested with small-size files):
public class FileUploadActivity extends Activity {
private final Context mContext = this;
HttpEntity httpEntity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_file_upload);
Drawable drawable = getResources().getDrawable(R.drawable.ic_action_home);
if (drawable != null) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
final byte[] bitmapdata = stream.toByteArray();
String url = "http://10.0.2.2/api/fileupload";
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
// Add binary body
if (bitmapdata != null) {
ContentType contentType = ContentType.create("image/png");
String fileName = "ic_action_home.png";
builder.addBinaryBody("file", bitmapdata, contentType, fileName);
httpEntity = builder.build();
MyRequest myRequest = new MyRequest(Request.Method.POST, url, new Response.Listener<NetworkResponse>() {
@Override
public void onResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
Toast.makeText(mContext, jsonString, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(mContext, error.toString(), Toast.LENGTH_SHORT).show();
}
}) {
@Override
public String getBodyContentType() {
return httpEntity.getContentType().getValue();
}
@Override
public byte[] getBody() throws AuthFailureError {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
httpEntity.writeTo(bos);
} catch (IOException e) {
VolleyLog.e("IOException writing to ByteArrayOutputStream");
}
return bos.toByteArray();
}
};
MySingleton.getInstance(this).addToRequestQueue(myRequest);
}
}
}
...
}
public class MyRequest extends Request<NetworkResponse>
这篇关于通过故障凌空发送分段文件与边界的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!