Post multipart request with Android SDK

前端 未结 12 1818
余生分开走
余生分开走 2020-11-22 04:38

I\'m trying to do something I thought would be relatively simple: Upload an image to a server with the Android SDK. I\'m found a lot of example code:

http://groups.g

相关标签:
12条回答
  • 2020-11-22 05:22

    More easy, light (32k), and many more performance:

    Android Asynchronous Http Client library: http://loopj.com/android-async-http/

    Implementation:

    How to send a “multipart/form-data” POST in Android with Volley

    0 讨论(0)
  • 2020-11-22 05:25

    Remove all your httpclient, httpmime dependency and add this dependency compile 'commons-httpclient:commons-httpclient:3.1'. This dependency has built in MultipartRequestEntity so that you can easily upload one or more files to the server

    public class FileUploadUrlConnection extends AsyncTask<String, String, String> {
    private Context context;
    private String url;
    private List<File> files;
    
    public FileUploadUrlConnection(Context context, String url, List<File> files) {
        this.context = context;
        this.url = url;
        this.files = files;
    }
    
    @Override
    protected String doInBackground(String... params) {
    
        HttpClient client = new HttpClient();
        PostMethod post = new PostMethod(url);
        HttpClientParams connectionParams = new HttpClientParams();
    
        post.setRequestHeader(// Your header goes here );
    
        try {
            Part[] parts = new Part[files.size()];
            for (int i=0; i<files.size(); i++) {
                Part part = new FilePart(files.get(i).getName(), files.get(i));
                parts[i] = part;
            }
    
            MultipartRequestEntity entity = new MultipartRequestEntity(parts, connectionParams);
    
            post.setRequestEntity(entity);
    
            int statusCode = client.executeMethod(post);
            String response = post.getResponseBodyAsString();
    
            Log.v("Multipart "," "+response);
            if(statusCode == 200) {
                return response;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } 
     return null;
    }
    

    You can also add the request and response timeout

    client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000);
    client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 10000);
    
    0 讨论(0)
  • 2020-11-22 05:26
    public class Multipart{
        private final Map<String, String> headrs;
        private String url;
        private HttpURLConnection con;
        private OutputStream os;
    
        private String delimiter = "--";
        private String boundary = "TRR" + Long.toString(System.currentTimeMillis()) + "TRR";
    
        public Multipart (String url, Map<String, String> headers) {
            this.url = url;
            this.headrs = headers;
        }
    
        public void connectForMultipart() throws Exception {
            con = (HttpURLConnection) (new URL(url)).openConnection();
            con.setRequestMethod("POST");
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setRequestProperty("Connection", "Keep-Alive");
            for (Map.Entry<String, String> entry : headrs.entrySet()) {
                con.setRequestProperty(entry.getKey(), entry.getValue());
            }
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            con.connect();
            os = con.getOutputStream();
        }
    
        public void addFormPart(String paramName, String value) throws Exception {
            writeParamData(paramName, value);
        }
    
        public void addFilePart(String paramName, String fileName, byte[] data) throws Exception {
            os.write((delimiter + boundary + "\r\n").getBytes());
            os.write(("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + fileName + "\"\r\n").getBytes());
            os.write(("Content-Type: application/octet-stream\r\n").getBytes());
            os.write(("Content-Transfer-Encoding: binary\r\n").getBytes());
            os.write("\r\n".getBytes());
    
            os.write(data);
    
            os.write("\r\n".getBytes());
        }
    
        public void finishMultipart() throws Exception {
            os.write((delimiter + boundary + delimiter + "\r\n").getBytes());
        }
    
    
        public String getResponse() throws Exception {
            InputStream is = con.getInputStream();
            byte[] b1 = new byte[1024];
            StringBuffer buffer = new StringBuffer();
    
            while (is.read(b1) != -1)
                buffer.append(new String(b1));
    
            con.disconnect();
    
            return buffer.toString();
        }
    
    
        private void writeParamData(String paramName, String value) throws Exception {
    
    
            os.write((delimiter + boundary + "\r\n").getBytes());
            os.write("Content-Type: text/plain\r\n".getBytes());//;charset=utf-8
            os.write(("Content-Disposition: form-data; name=\"" + paramName + "\"\r\n").getBytes());
            ;
            os.write(("\r\n" + value + "\r\n").getBytes());
    
    
        }
    }
    

    Then call below

    Multipart multipart = new Multipart(url__, map);
                multipart .connectForMultipart();
    multipart .addFormPart(entry.getKey(), entry.getValue());
    multipart .addFilePart(KeyName, "FileName", imagedata);
    multipart .finishMultipart();
    
    0 讨论(0)
  • 2020-11-22 05:27

    Here is a Simple approach if you are using the AOSP library Volley.

    Extend the class Request<T> as follows-

    public class MultipartRequest extends Request<String> {
        private static final String FILE_PART_NAME = "file";
        private final Response.Listener<String> mListener;
        private final Map<String, File> mFilePart;
        private final Map<String, String> mStringPart;
        MultipartEntityBuilder entity = MultipartEntityBuilder.create();
        HttpEntity httpentity;
    
        public MultipartRequest(String url, Response.ErrorListener errorListener,
                                Response.Listener<String> listener, Map<String, File> file,
                                Map<String, String> mStringPart) {
            super(Method.POST, url, errorListener);
            mListener = listener;
            mFilePart = file;
            this.mStringPart = mStringPart;
            entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            buildMultipartEntity();
        }
    
        public void addStringBody(String param, String value) {
            mStringPart.put(param, value);
        }
    
        private void buildMultipartEntity() {
            for (Map.Entry<String, File> entry : mFilePart.entrySet()) {
                // entity.addPart(entry.getKey(), new FileBody(entry.getValue(), ContentType.create("image/jpeg"), entry.getKey()));
                try {
                    entity.addBinaryBody(entry.getKey(), Utils.toByteArray(new FileInputStream(entry.getValue())), ContentType.create("image/jpeg"), entry.getKey() + ".JPG");
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }
            for (Map.Entry<String, String> entry : mStringPart.entrySet()) {
                if (entry.getKey() != null && entry.getValue() != null) {
                    entity.addTextBody(entry.getKey(), entry.getValue());
                }
            }
        }
    
        @Override
        public String getBodyContentType() {
            return httpentity.getContentType().getValue();
        }
    
        @Override
        public byte[] getBody() throws AuthFailureError {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                httpentity = entity.build();
                httpentity.writeTo(bos);
            } catch (IOException e) {
                VolleyLog.e("IOException writing to ByteArrayOutputStream");
            }
            return bos.toByteArray();
        }
    
        @Override
        protected Response<String> parseNetworkResponse(NetworkResponse response) {
            Log.d("Response", new String(response.data));
            return Response.success(new String(response.data), getCacheEntry());
        }
    
        @Override
        protected void deliverResponse(String response) {
            mListener.onResponse(response);
        }
    }
    

    You can create and add a request like-

    Map<String, String> params = new HashMap<>();
            params.put("name", name.getText().toString());
            params.put("email", email.getText().toString());
            params.put("user_id", appPreferences.getInt( Utils.PROPERTY_USER_ID, -1) + "");
            params.put("password", password.getText().toString());
            params.put("imageName", pictureName);
            Map<String, File> files = new HashMap<>();
            files.put("photo", new File(Utils.LOCAL_RESOURCE_PATH + pictureName));
            MultipartRequest multipartRequest = new MultipartRequest(Utils.BASE_URL + "editprofile/" + appPreferences.getInt(Utils.PROPERTY_USER_ID, -1), new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    // TODO Auto-generated method stub
                    Log.d("Error: ", error.toString());
                    FugaDialog.showErrorDialog(ProfileActivity.this);
                }
            }, new Response.Listener<String>() {
                @Override
                public void onResponse(String jsonResponse) {
                    JSONObject response = null;
                    try {
                        Log.d("jsonResponse: ", jsonResponse);
                        response = new JSONObject(jsonResponse);
    
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    try {
                        if (response != null && response.has("statusmessage") && response.getBoolean("statusmessage")) {
                            updateLocalRecord();
    
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                    FugaDialog.dismiss();
                }
    
            }, files, params);
            RequestQueue queue = Volley.newRequestQueue(this);
            queue.add(multipartRequest);
    
    0 讨论(0)
  • 2020-11-22 05:33

    Update April 29th 2014:

    My answer is kind of old by now and I guess you rather want to use some kind of high level library such as Retrofit.


    Based on this blog I came up with the following solution: http://blog.tacticalnuclearstrike.com/2010/01/using-multipartentity-in-android-applications/

    You will have to download additional libraries to get MultipartEntity running!

    1) Download httpcomponents-client-4.1.zip from http://james.apache.org/download.cgi#Apache_Mime4J and add apache-mime4j-0.6.1.jar to your project.

    2) Download httpcomponents-client-4.1-bin.zip from http://hc.apache.org/downloads.cgi and add httpclient-4.1.jar, httpcore-4.1.jar and httpmime-4.1.jar to your project.

    3) Use the example code below.

    private DefaultHttpClient mHttpClient;
    
    
    public ServerCommunication() {
        HttpParams params = new BasicHttpParams();
        params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
        mHttpClient = new DefaultHttpClient(params);
    }
    
    
    public void uploadUserPhoto(File image) {
    
        try {
    
            HttpPost httppost = new HttpPost("some url");
    
            MultipartEntity multipartEntity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);  
            multipartEntity.addPart("Title", new StringBody("Title"));
            multipartEntity.addPart("Nick", new StringBody("Nick"));
            multipartEntity.addPart("Email", new StringBody("Email"));
            multipartEntity.addPart("Description", new StringBody(Settings.SHARE.TEXT));
            multipartEntity.addPart("Image", new FileBody(image));
            httppost.setEntity(multipartEntity);
    
            mHttpClient.execute(httppost, new PhotoUploadResponseHandler());
    
        } catch (Exception e) {
            Log.e(ServerCommunication.class.getName(), e.getLocalizedMessage(), e);
        }
    }
    
    private class PhotoUploadResponseHandler implements ResponseHandler<Object> {
    
        @Override
        public Object handleResponse(HttpResponse response)
                throws ClientProtocolException, IOException {
    
            HttpEntity r_entity = response.getEntity();
            String responseString = EntityUtils.toString(r_entity);
            Log.d("UPLOAD", responseString);
    
            return null;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 05:34

    I highly recommend Loopj.

    I have successfully used it to upload multiple files at once, including different mime types. Simply do this:

    File myVideo = new File("/path/to/myvideo.mp4");
    File myPic = new File("/path/to/mypic.jpg");
    RequestParams params = new RequestParams();
    try {
      params.put("profile_picture", myPic);
      params.put("my_video", myVideo);
    } catch(FileNotFoundException e) {}
    

    For large or many files you might have to increase the timeout amount else the default timeout is used which might be too short:

    client.setTimeout(500000) //make this the appropriate timeout in milliseconds
    

    Please see this links for a full description of loopj and how to use it, by far the easiest async http library I have come across:

    http://loopj.com/android-async-http/ http://loopj.com/android-async-http/doc/com/loopj/android/http/AsyncHttpClient.html

    0 讨论(0)
提交回复
热议问题