在Android中发布包含图片的多部分请求?

时间:2013-11-09 14:15:05

标签: java android json http java-ee

我正在尝试将我的对象的JSON表示和可选图像发布到我的Spring后端。但是,我在发布带图像的请求时遇到了很大的麻烦。我已设法将第一部分发布到服务器; JSON对象。但是当我尝试添加第二部分时,用户捕获的图像没有任何反应。我没有看到任何堆栈痕迹。

我做错了什么以及如何在请求中发布图片。这就是我的......

String boundary = UUID.randomUUID().toString();
String twoHyphens = "--";
String attachmentName = "data";
String crlf = "\r\n";


try {
    URI uri = new URI("http://myappserver.com/app");
    HttpURLConnection urlConnection = (HttpURLConnection) uri.toURL().openConnection();
    urlConnection.setRequestMethod("POST");
    urlConnection.setRequestProperty("Connection", "Keep-Alive");
    urlConnection.setDoInput(true);
    urlConnection.setDoOutput(true);
    urlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

    DataOutputStream dos = new DataOutputStream(urlConnection.getOutputStream());

    InputStream inputStream = context.getContentResolver().openInputStream(question.getUri());

    // FIRST PART; A JSON object
    dos.writeBytes(twoHyphens + boundary);
    dos.writeBytes(crlf);
    dos.writeBytes("Content-Type: application/json");
    dos.writeBytes(crlf);
    dos.writeBytes("Content-Disposition: form-data; name=\"data\"");
    dos.writeBytes(crlf);
    dos.writeBytes(crlf);
    dos.writeBytes(jsonEntity);
    dos.writeBytes(crlf);

    // SECOND PART; A image..
    dos.writeBytes(twoHyphens + boundary);
    dos.writeBytes(crlf);
    dos.writeBytes("Content-Type: image/jpg");
    dos.writeBytes(crlf);
    dos.writeBytes("Content-Disposition: form-data; name=\"image\"");
    dos.writeBytes(crlf);
    dos.writeBytes(crlf);

    // Something must be done here. I guess I must encode it to Base64 here.
    // How can I avoid loading the whole image at once so I don't get out of memory errors.

    dos.writeBytes(crlf);
    dos.writeBytes(twoHyphens + boundary + twoHyphens + crlf);
    dos.close();
} catch (Exception e) {

}

2 个答案:

答案 0 :(得分:2)

代码说明了如何发送文件(这里是pdf)。通过它,调试代码将对您有所帮助。

int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
int maxBufferSize = 1 * 1024 * 1024;
FileInputStream fileInputStream = new FileInputStream(file);

dos.writeBytes(twoHyphens + boundary + lineEnd); 
dos.writeBytes("Content-Disposition: form-data; name=\"attachment_0\";filename=\"" + file.getName() + "\"" + lineEnd);
dos.writeBytes("Content-Type: text/pdf" + lineEnd);
dos.writeBytes("Content-Length: " + file.length() + lineEnd);    
dos.writeBytes(lineEnd);        
bytesAvailable = fileInputStream.available(); 
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer = new byte[bufferSize];
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); 
}   

dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
fileInputStream.close();
}

//发送参数,见下文,key是webservice参数的关键。

dos.writeBytes("Content-Disposition: form-data; name=\""+key+"\"" + lineEnd);
dos.writeBytes(lineEnd);
dos.writeBytes(requestData.get(key).toString() + lineEnd);

答案 1 :(得分:1)

下面是我使用HttpURLConnection类实现的MULTIPART表单数据上传。此类使用动态用法,以便可以使用不同的数据集一次调用多个请求。 注意:我将json部分分成单独的文本形式,以保持与我的服务器的一致性。您可以修改它以符合您的服务器要求。

public class WebConnector {
String boundary = "-------------" + System.currentTimeMillis();
private static final String LINE_FEED = "\r\n";
private static final String TWO_HYPHENS = "--";


private StringBuilder url;
private String protocol;
private HashMap<String, String> params;
private JSONObject postData;
private List<String> fileList;
private int count = 0;
private DataOutputStream dos;

public WebConnector(StringBuilder url, String protocol,
                    HashMap<String, String> params, JSONObject postData) {
    super();
    this.url = url;
    this.protocol = protocol;
    this.params = params;
    this.postData = postData;
    createServiceUrl();
}

public WebConnector(StringBuilder url, String protocol,
                    HashMap<String, String> params, JSONObject postData, List<String> fileList) {
    super();
    this.url = url;
    this.protocol = protocol;
    this.params = params;
    this.postData = postData;
    this.fileList = fileList;
    createServiceUrl();
}

public String connectToMULTIPART_POST_service(String postName) {


    System.out.println(">>>>>>>>>url : " + url);

    StringBuilder stringBuilder = new StringBuilder();

    String strResponse = "";
    InputStream inputStream = null;
    HttpURLConnection urlConnection = null;

    try {
        urlConnection = (HttpURLConnection) new URL(url.toString()).openConnection();
        urlConnection.setRequestProperty("Accept", "application/json");
        urlConnection.setRequestProperty("Connection", "close");
        urlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 ( compatible ) ");
        urlConnection.setRequestProperty("Authorization", "Bearer " + Config.getConfigInstance().getAccessToken());
        urlConnection.setRequestProperty("Content-type", "multipart/form-data; boundary=" + boundary);

        urlConnection.setDoOutput(true);
        urlConnection.setDoInput(true);
        urlConnection.setUseCaches(false);
        urlConnection.setChunkedStreamingMode(1024);
        urlConnection.setRequestMethod("POST");
        dos = new DataOutputStream(urlConnection.getOutputStream());

        Iterator<String> keys = postData.keys();
        while (keys.hasNext()) {
            try {
                String id = String.valueOf(keys.next());
                addFormField(id, "" + postData.get(id));
                System.out.println(id + " : " + postData.get(id));
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
        try {
            dos.writeBytes(LINE_FEED);
            dos.flush();
            dos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (fileList != null && fileList.size() > 0 && !fileList.isEmpty()) {
            for (int i = 0; i < fileList.size(); i++) {

                File file = new File(fileList.get(i));
                if (file != null) ;
                addFilePart("photos[" + i + "][image]", file);
            }
        }
        // forming th java.net.URL object

        build();
        urlConnection.connect();
        int statusCode = 0;
        try {
            urlConnection.connect();
            statusCode = urlConnection.getResponseCode();
        } catch (EOFException e1) {
            if (count < 5) {
                urlConnection.disconnect();
                count++;
                String temp = connectToMULTIPART_POST_service(postName);
                if (temp != null && !temp.equals("")) {
                    return temp;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 200 represents HTTP OK
        if (statusCode == HttpURLConnection.HTTP_OK) {
            inputStream = new BufferedInputStream(urlConnection.getInputStream());
            strResponse = readStream(inputStream);
        } else {
            System.out.println(urlConnection.getResponseMessage());
            inputStream = new BufferedInputStream(urlConnection.getInputStream());
            strResponse = readStream(inputStream);
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (null != inputStream)
                inputStream.close();
        } catch (IOException e) {
        }
    }
    return strResponse;
}

public void addFormField(String fieldName, String value) {
    try {
        dos.writeBytes(TWO_HYPHENS + boundary + LINE_FEED);
        dos.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\"" + LINE_FEED + LINE_FEED/*+ value + LINE_FEED*/);
        /*dos.writeBytes("Content-Type: text/plain; charset=UTF-8" + LINE_FEED);*/
        dos.writeBytes(value + LINE_FEED);
    } catch (IOException e) {
        e.printStackTrace();
    }

}

public void addFilePart(String fieldName, File uploadFile) {
    try {
        dos.writeBytes(TWO_HYPHENS + boundary + LINE_FEED);
        dos.writeBytes("Content-Disposition: form-data; name=\"" + fieldName + "\";filename=\"" + uploadFile.getName() + "\"" + LINE_FEED);
        dos.writeBytes(LINE_FEED);

        FileInputStream fStream = new FileInputStream(uploadFile);
        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        int length = -1;

        while ((length = fStream.read(buffer)) != -1) {
            dos.write(buffer, 0, length);
        }
        dos.writeBytes(LINE_FEED);
        dos.writeBytes(TWO_HYPHENS + boundary + TWO_HYPHENS + LINE_FEED);
    /* close streams */
        fStream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void addHeaderField(String name, String value) {
    try {
        dos.writeBytes(name + ": " + value + LINE_FEED);
    } catch (IOException e) {
        e.printStackTrace();
    }

}

public void build() {
    try {
        dos.writeBytes(LINE_FEED);
        dos.flush();
        dos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private static String readStream(InputStream in) {
    StringBuilder sb = new StringBuilder();
    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String nextLine = "";
        while ((nextLine = reader.readLine()) != null) {
            sb.append(nextLine);
        }
    /* Close Stream */
        if (null != in) {
            in.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return sb.toString();
}

private void createServiceUrl() {
    if (null == params) {
        return;
    }
    final Iterator<Map.Entry<String, String>> it = params.entrySet().iterator();
    boolean isParam = false;
    while (it.hasNext()) {
        final Map.Entry<String, String> mapEnt = (Map.Entry<String, String>) it.next();
        url.append(mapEnt.getKey());
        url.append("=");
        try {
            url.append(URLEncoder.encode(mapEnt.getValue(), "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        url.append(WSConstants.AMPERSAND);
        isParam = true;
    }
    if (isParam) {
        url.deleteCharAt(url.length() - 1);
    }
}

}