वॉली के साथ Android में एक "मल्टीपार्ट / फॉर्म-डेटा" POST कैसे भेजें


89

क्या कोई multipart/form-dataअभी तक वॉली के साथ एंड्रॉइड में POST भेजने में सक्षम है ? मुझे image/pngहमारे सर्वर पर POST अनुरोध का उपयोग करके अपलोड करने में कोई सफलता नहीं मिली है और अगर किसी के पास है तो मैं उत्सुक हूं।

मेरा मानना ​​है कि ऐसा करने का डिफ़ॉल्ट तरीका वर्ग public byte[] getPostBody()में ओवरराइड करना होगा Request.javaऔर Fileसीमा के लिए एक खाली हैडर कुंजी के साथ वहां संलग्न करना होगा। हालाँकि, मेरी फ़ाइल को एक के Stringलिए परिवर्तित करना Map<String, String> postParamsऔर फिर इसे फिर से एन्कोड किया जाना वास्तव में सुरुचिपूर्ण नहीं है। इसके अलावा मैं अपने प्रयासों में असफल रहा हूं। यह वास्तव में एकमात्र चीज है जो हमें इस पुस्तकालय में स्विच करने से पीछे रखती है।

वैसे भी, सभी विचारों और उत्तरों की बहुत सराहना की जाती है। आपके सहयोग के लिए धन्यवाद।

जवाबों:


75

मैं इस पर गलत हो सकता हूं लेकिन मुझे लगता है कि आपको इसके com.android.volley.toolbox.HttpStackलिए खुद को लागू करने की आवश्यकता है क्योंकि डिफ़ॉल्ट वाले ( HurlStackयदि संस्करण> जिंजरब्रेड या HttpClientStack) के साथ सौदा नहीं करते हैं multipart/form-data

संपादित करें:

और वास्तव में मैं गलत था। मैं इसे 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);
    }
}

यह बहुत कच्चा है लेकिन मैंने इसे एक छवि और एक साधारण स्ट्रिंग के साथ आज़माया है और यह काम करता है। प्रतिक्रिया एक प्लेसहोल्डर है, इस मामले में एक प्रतिक्रिया स्ट्रिंग को वापस करने के लिए बहुत अर्थ नहीं है। मुझे MultipartEntity का उपयोग करने के लिए अपाचे httpmime का उपयोग करने में समस्याएँ आईं, इसलिए मैंने इस https://code.google.com/p/httpclientandroidlib/ का उपयोग किया है, यदि बेहतर तरीका नहीं है तो मुझे नहीं पता। आशा करता हूँ की ये काम करेगा।

संपादित करें

Httpclientandroidlib का उपयोग किए बिना आप httpmime का उपयोग कर सकते हैं, केवल निर्भरता httpcore है।


2
@LOG_TAG: यह बड़ी फ़ाइलों का समर्थन नहीं करेगा। न ही यह एक प्रगति बार का समर्थन करेगा। कारण यह है कि यह एक बाइट [] में सभी डेटा डाल देगा। बड़ी फ़ाइलों के लिए, आप एक इनपुटस्ट्रीम का उपयोग करना चाहते हैं, जो वॉली के साथ संभव नहीं लगता है। लेकिन वे (वॉली देव) साथ ही कहते हैं कि वॉली बड़ी फ़ाइलों के लिए नहीं बना है।
पैट्रिक बूस

9
@alex क्या आप MultipartRequest का उपयोग करने के लिए कुछ कोड डाल सकते हैं?
कृष्ण श्रेष्ठ

4
मुझे यह त्रुटि मिलती है: java.lang.NoClassDefFoundError: org.apache.http.entity.ContentType
मिलाद

1
Apache http का उपयोग कर बहुस्तरीयता। मैं इसे अपाचे मल्टीपार्ट लाइब्रेरी के बिना करना चाहता हूं। मैं यह कैसे कर सकता हूँ।
जोसेफ नोव

1
वापसी संस्था .getContentType ()। getValue (); त्रुटि
वलोडिमिर कुल्क

14

जैसा कि I / O (लगभग 4:05) में प्रस्तुति में उल्लेख किया गया है, बड़े पेलोड के लिए वॉली "भयानक" है। जैसा कि मैं इसे समझता हूं कि फ़ाइलों को प्राप्त / भेजने (बड़ी) के लिए वॉली का उपयोग न करने का मतलब है। कोड को देखते हुए ऐसा लगता है कि इसे मल्टीपार्ट फॉर्म डेटा को संभालने के लिए भी नहीं बनाया गया है। [], आदि...)। संभवत: आप कार्यान्वयन बना पाएंगे जो कि मल्टीपार्ट को संभाल सकता है लेकिन अगर मैं आप होते तो मैं सिर्फ मल्टीपार्ट के साथ सीधे HttpClient का उपयोग कर सकता हूं जैसे:

    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 के साथ वॉली का उपयोग करें


1
मदद के लिए बहुत बहुत धन्यवाद, आपका ब्लॉग मुझे कुछ ऐसा दिखाता है जो मेरे पास नहीं था। मैं ऊपर दिए गए लिंक के माध्यम से आपके सुझाव की कोशिश करूंगा यदि मुझे एलेक्स का समाधान काम करने के लिए नहीं मिल सकता है। चीयर्स!
AllDayAmazing

नमस्कार @Ogre_BGR, क्या आप कृपया एक पूर्ण नमूना प्रदान कर सकते हैं कि आप स्नैप कोड का उपयोग करके छवि कैसे अपलोड करें। मैंने कई नमूने लेने की कोशिश की, लेकिन वे बहुत पुराने हैं और मुझे यह काम करने के लिए नहीं मिला। धन्यवाद
थियागो

मल्टीपार्ट अब समर्थित है। इस पृष्ठ पर अन्य उत्तरों को देखें।
मार्टिन कोन्सेनी

1
@MartinKonecny ​​कृपया अपनी टिप्पणी में सही उत्तर लिंक करें ताकि अन्य उपयोगकर्ता सीधे इसमें जा सकें
Ognyan

मैं एक ही अनुरोध में मल्टीपार्ट प्रारूप के साथ अन्य मापदंडों को कैसे जोड़ सकता हूं?
कैसिलास

10

अद्यतन 2015/08/26:

यदि आप हटाए गए HttpEntity का उपयोग नहीं करना चाहते हैं, तो यहां मेरा काम करने का नमूना कोड (ASP.Net परीक्षण के साथ परीक्षण किया गया) है

MultipartActivity.java

package com.example.volleyapp;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.view.Menu;
import android.view.MenuItem;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.example.volleyapp.BaseVolleyRequest;
import com.example.volleyapp.VolleySingleton;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class MultipartActivity extends Activity {

    final Context mContext = this;
    String mimeType;
    DataOutputStream dos = null;
    String lineEnd = "\r\n";
    String boundary = "apiclient-" + System.currentTimeMillis();
    String twoHyphens = "--";
    int bytesRead, bytesAvailable, bufferSize;
    byte[] buffer;
    int maxBufferSize = 1024 * 1024;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_multipart);             

        Drawable drawable = ContextCompat.getDrawable(mContext, R.drawable.ic_action_file_attachment_light);
        Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
        final byte[] bitmapData = byteArrayOutputStream.toByteArray();
        String url = "http://192.168.1.100/api/postfile";

        mimeType = "multipart/form-data;boundary=" + boundary;

        BaseVolleyRequest baseVolleyRequest = new BaseVolleyRequest(1, url, new Response.Listener<NetworkResponse>() {
            @Override
            public void onResponse(NetworkResponse response) {

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {

            }
        }) {
            @Override
            public String getBodyContentType() {
                return mimeType;
            }

            @Override
            public byte[] getBody() throws AuthFailureError {
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                dos = new DataOutputStream(bos);
                try {
                    dos.writeBytes(twoHyphens + boundary + lineEnd);
                    dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\""
                            + "ic_action_file_attachment_light.png" + "\"" + lineEnd);
                    dos.writeBytes(lineEnd);
                    ByteArrayInputStream fileInputStream = new ByteArrayInputStream(bitmapData);
                    bytesAvailable = fileInputStream.available();

                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    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;
            }
        };

        VolleySingleton.getInstance(mContext).addToRequestQueue(baseVolleyRequest);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_multipart, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

BaseVolleyRequest.java:

package com.example.volleyapp;

import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.JsonSyntaxException;


public class BaseVolleyRequest extends Request<NetworkResponse> {

    private final Response.Listener<NetworkResponse> mListener;
    private final Response.ErrorListener mErrorListener;

    public BaseVolleyRequest(String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
        super(0, url, errorListener);
        this.mListener = listener;
        this.mErrorListener = errorListener;
    }

    public BaseVolleyRequest(int method, String url, Response.Listener<NetworkResponse> listener, Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mListener = listener;
        this.mErrorListener = errorListener;
    }

    @Override
    protected Response<NetworkResponse> parseNetworkResponse(NetworkResponse response) {
        try {
            return Response.success(
                    response,
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (JsonSyntaxException e) {
            return Response.error(new ParseError(e));
        } catch (Exception e) {
            return Response.error(new ParseError(e));
        }
    }

    @Override
    protected void deliverResponse(NetworkResponse response) {
        mListener.onResponse(response);
    }

    @Override
    protected VolleyError parseNetworkError(VolleyError volleyError) {
        return super.parseNetworkError(volleyError);
    }

    @Override
    public void deliverError(VolleyError error) {
        mErrorListener.onErrorResponse(error);
    }
}

अद्यतन का अंत

यह मेरा कार्य नमूना कोड है (केवल छोटे आकार की फ़ाइलों के साथ परीक्षण किया गया है):

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>

3
कुछ सर्वर बहुत picky हैं। यदि आपके पास कोई समस्या है, तो " और "फ़ाइल नाम =" सामग्री-विवाद का निर्माण करते समय और "मल्टीपार्ट / फॉर्म-डेटा; सीमा =" + सीमा;
केविन

आपकी टिप्पणी के लिए धन्यवाद @ केविन। वास्तव में, मेरे पास कई सर्वर ऐप्स नहीं हैं जो यह जांच
सकें

@HemsLodha: कृपया मेरी निम्नलिखित प्रश्न पर RacZo के जवाब पर एक नज़र डालें stackoverflow.com/questions/32240177/... अगर यह आप या नहीं मदद कर सकते हैं :) देखने के लिए
बीएनके

1
मैं वॉली के साथ पोस्ट मल्टीपार्ट अनुरोध भेज रहा हूं और अंत में url को पैरामीटर सेट करता हूं और यह काम करता है। मदद के लिए धन्यवाद @BNK।
जोसेफ

@ user3561494 it's वीडियो के रूप में बड़े आकार की फ़ाइलों के लिए अनुशंसित नहीं है
BNK

9

अपलोड प्रगति के साथ मल्टीपार्ट अनुरोध पूरा करें

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.util.CharsetUtils;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyLog;
import com.beusoft.app.AppContext;

public class MultipartRequest extends Request<String> {

    MultipartEntityBuilder entity = MultipartEntityBuilder.create();
    HttpEntity httpentity;
    private String FILE_PART_NAME = "files";

    private final Response.Listener<String> mListener;
    private final File mFilePart;
    private final Map<String, String> mStringPart;
    private Map<String, String> headerParams;
    private final MultipartProgressListener multipartProgressListener;
    private long fileLength = 0L;

    public MultipartRequest(String url, Response.ErrorListener errorListener,
            Response.Listener<String> listener, File file, long fileLength,
            Map<String, String> mStringPart,
            final Map<String, String> headerParams, String partName,
            MultipartProgressListener progLitener) {
        super(Method.POST, url, errorListener);

        this.mListener = listener;
        this.mFilePart = file;
        this.fileLength = fileLength;
        this.mStringPart = mStringPart;
        this.headerParams = headerParams;
        this.FILE_PART_NAME = partName;
        this.multipartProgressListener = progLitener;

        entity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        try {
            entity.setCharset(CharsetUtils.get("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        buildMultipartEntity();
        httpentity = entity.build();
    }

    // public void addStringBody(String param, String value) {
    // if (mStringPart != null) {
    // mStringPart.put(param, value);
    // }
    // }

    private void buildMultipartEntity() {
        entity.addPart(FILE_PART_NAME, new FileBody(mFilePart, ContentType.create("image/gif"), mFilePart.getName()));
        if (mStringPart != null) {
            for (Map.Entry<String, String> entry : mStringPart.entrySet()) {
                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.writeTo(new CountingOutputStream(bos, fileLength,
                    multipartProgressListener));
        } catch (IOException e) {
            VolleyLog.e("IOException writing to ByteArrayOutputStream");
        }
        return bos.toByteArray();
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {

        try {
//          System.out.println("Network Response "+ new String(response.data, "UTF-8"));
            return Response.success(new String(response.data, "UTF-8"),
                    getCacheEntry());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            // fuck it, it should never happen though
            return Response.success(new String(response.data), getCacheEntry());
        }
    }

    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }

//Override getHeaders() if you want to put anything in header

    public static interface MultipartProgressListener {
        void transferred(long transfered, int progress);
    }

    public static class CountingOutputStream extends FilterOutputStream {
        private final MultipartProgressListener progListener;
        private long transferred;
        private long fileLength;

        public CountingOutputStream(final OutputStream out, long fileLength,
                final MultipartProgressListener listener) {
            super(out);
            this.fileLength = fileLength;
            this.progListener = listener;
            this.transferred = 0;
        }

        public void write(byte[] b, int off, int len) throws IOException {
            out.write(b, off, len);
            if (progListener != null) {
                this.transferred += len;
                int prog = (int) (transferred * 100 / fileLength);
                this.progListener.transferred(this.transferred, prog);
            }
        }

        public void write(int b) throws IOException {
            out.write(b);
            if (progListener != null) {
                this.transferred++;
                int prog = (int) (transferred * 100 / fileLength);
                this.progListener.transferred(this.transferred, prog);
            }
        }

    }
}

नमूना उपयोग

protected <T> void uploadFile(final String tag, final String url,
            final File file, final String partName,         
            final Map<String, String> headerParams,
            final Response.Listener<String> resultDelivery,
            final Response.ErrorListener errorListener,
            MultipartProgressListener progListener) {
        AZNetworkRetryPolicy retryPolicy = new AZNetworkRetryPolicy();

        MultipartRequest mr = new MultipartRequest(url, errorListener,
                resultDelivery, file, file.length(), null, headerParams,
                partName, progListener);

        mr.setRetryPolicy(retryPolicy);
        mr.setTag(tag);

        Volley.newRequestQueue(this).add(mr);

    }

Hi @AZ_ - मैंने आपके कोड की कोशिश की: लेकिन मुझे यह त्रुटि मिली: MultipartRequest.getBody: IOException लेखन ByteArrayOutputStream। क्या आप कृपया मदद कर सकते हैं
थियागो

मेरे पास आपका कोड नहीं है, मैं एक और प्रश्न को खोलने के लिए कुछ भी बेहतर नहीं सुझा सकता, सबसे संभावित कारण यह हो सकता है कि आप वर्चुअल मेमोरी से बाहर भाग गए।
AZ_

1
मेरे पास ओपन I नया प्रश्न है: stackoverflow.com/questions/31474585/… क्या आप pls मदद कर सकते हैं। धन्यवाद
थियागो

मैं एक ही अनुरोध में मल्टीपार्ट प्रारूप के साथ अन्य मापदंडों को कैसे जोड़ सकता हूं?
कैसिलास

@ कैसिलस अनुरोध के शीर्ष लेख में मुख्य मूल्य जोड़ी जोड़ते हैं।
AZ_

8

देव के लिए एक बहुत ही सरल दृष्टिकोण जो सिर्फ मल्टीपार्ट अनुरोध में POST पैरामीटर भेजना चाहते हैं।

कक्षा में निम्नलिखित परिवर्तन करें जो अनुरोध को बढ़ाता है। जावा

पहले इन स्थिरांक को परिभाषित करें:

String BOUNDARY = "s2retfgsGSRFsERFGHfgdfgw734yhFHW567TYHSrf4yarg"; //This the boundary which is used by the server to split the post parameters.
String MULTIPART_FORMDATA = "multipart/form-data;boundary=" + BOUNDARY;

आपके लिए एक पोस्ट बॉडी बनाने के लिए एक सहायक फ़ंक्शन जोड़ें:

private String createPostBody(Map<String, String> params) {
        StringBuilder sbPost = new StringBuilder();
        if (params != null) {
            for (String key : params.keySet()) {
                if (params.get(key) != null) {
                    sbPost.append("\r\n" + "--" + BOUNDARY + "\r\n");
                    sbPost.append("Content-Disposition: form-data; name=\"" + key + "\"" + "\r\n\r\n");
                    sbPost.append(params.get(key).toString());
                }
            }
        }
        return sbPost.toString();
    } 

ओवरराइड getBody () और getBodyContentType

public String getBodyContentType() {
    return MULTIPART_FORMDATA;
}

public byte[] getBody() throws AuthFailureError {
        return createPostBody(getParams()).getBytes();
}

1
बहुत ही सरल और पूरी तरह से काम करता है! मैं पड़ा sbPost.append("--" + BOUNDARY + "--");सही इससे पहले कि मैं वापस जाने के बाद से एपीआई मैं उपयोग कर रहा हूँ एक बंद टैग की आवश्यकता है
सायरन

1
बहुत बहुत धन्यवाद :)
अर्पित रतन

धन्यवाद! इसने मेरे लिए फ्रंट-एंड पर काम किया लेकिन बैक-एंड विशेष रूप से नोडज को इसे पार्स करने में परेशानी हो रही है? क्या आपको इसका कोई अनुभव हुआ?
वोपी

1
क्षमा करें, मेरे पास बैकेंड का अनुभव नहीं है :(
अर्पित रतन

@Arpit धन्यवाद, मैं gist.github.com/anggadarkprince/… के
Woppi

4

एसओ पर पहला जवाब।

मैंने एक ही समस्या का सामना किया है और @alex का कोड बहुत उपयोगी पाया है। मैंने कुछ सरल संशोधन किए हैं ताकि हशप के माध्यम से आवश्यकतानुसार कई मापदंडों को पारित किया जा सके, और मूल रूप से स्ट्रिंगरप्लेस्ट से कॉपी parseNetworkResponse()किया गया है। मैंने ऑनलाइन खोज की है और यह पता लगाने के लिए बहुत आश्चर्यचकित हूं कि इस तरह के एक सामान्य कार्य का शायद ही कभी जवाब दिया जाता है। वैसे भी, मुझे लगता है कि कोड मदद कर सकता है:

public class MultipartRequest extends Request<String> {

private MultipartEntity entity = new MultipartEntity();

private static final String FILE_PART_NAME = "image";

private final Response.Listener<String> mListener;
private final File file;
private final HashMap<String, String> params;

public MultipartRequest(String url, Response.Listener<String> listener, Response.ErrorListener errorListener, File file, HashMap<String, String> params)
{
    super(Method.POST, url, errorListener);

    mListener = listener;
    this.file = file;
    this.params = params;
    buildMultipartEntity();
}

private void buildMultipartEntity()
{
    entity.addPart(FILE_PART_NAME, new FileBody(file));
    try
    {
        for ( String key : params.keySet() ) {
            entity.addPart(key, new StringBody(params.get(key)));
        }
    }
    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();
}

/**
 * copied from Android StringRequest class
 */
@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
protected void deliverResponse(String response)
{
    mListener.onResponse(response);
}

और आप निम्न के रूप में वर्ग का उपयोग कर सकते हैं:

    HashMap<String, String> params = new HashMap<String, String>();

    params.put("type", "Some Param");
    params.put("location", "Some Param");
    params.put("contact",  "Some Param");


    MultipartRequest mr = new MultipartRequest(url, new Response.Listener<String>(){

        @Override
        public void onResponse(String response) {
            Log.d("response", response);
        }

    }, new Response.ErrorListener(){

        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e("Volley Request Error", error.getLocalizedMessage());
        }

    }, f, params);

    Volley.newRequestQueue(this).add(mr);

0

एक और समाधान, पेलोड बड़े के साथ उच्च प्रदर्शन के साथ बहुत हल्का:

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!");

            };

        }

    );

}

2
बड़े फ़ाइल आकार स्मृति अपवाद को छोड़ देते हैं
रवि

1
@Ravi +1 यह लाइब्रेरी बड़ी फाइलों को अपलोड करने के लिए बेकार है
एंटोन

यदि आप बड़ी फ़ाइलों को मल्टीपार्ट के लिए अपाचे माइम पुस्तकालयों का उपयोग करना चाहते हैं तो इस पुस्तकालय का उपयोग करके इसे पोस्ट करें।
रवि ०

आपको छवि के आकार को संपीड़ित करने की आवश्यकता है और फिर इस लाइब्रेरी का उपयोग करें ताकि मुझे नीचे दिए गए URL से छवि का समाधान मिल सके: programmerguru.com/android-tutorial// मुझे उम्मीद है कि यह किसी का समय बचा सकता है।
मिलन शेठ

@ रावी अपाचे माइम आपको संघर्ष और डुप्लिकेट क्लास त्रुटि देगा।
मुहम्मद साकिब

0

वॉली एंड्रॉइड का उपयोग करके फ़ाइल अपलोड करने के लिए यहां सरल समाधान और पूर्ण उदाहरण है

1) ग्रेड आयात करें

compile 'dev.dworks.libs:volleyplus:+'

2) अब एक Class RequestManager बनाएं

public class RequestManager {
    private static RequestManager mRequestManager;
    /**
     * Queue which Manages the Network Requests :-)
     */
    private static RequestQueue mRequestQueue;
    // ImageLoader Instance

    private RequestManager() {

    }

    public static RequestManager get(Context context) {

        if (mRequestManager == null)
            mRequestManager = new RequestManager();

        return mRequestManager;
    }

    /**
     * @param context application context
     */
    public static RequestQueue getnstance(Context context) {

        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(context);
        }

        return mRequestQueue;

    }


}

3) अब फ़ाइल WebService अपलोड करने के लिए अनुरोध को संभालने के लिए एक क्लास बनाएँ

public class WebService {
    private RequestQueue mRequestQueue;
    private static WebService apiRequests = null;

    public static WebService getInstance() {
        if (apiRequests == null) {
            apiRequests = new WebService();
            return apiRequests;
        }
        return apiRequests;
    }
    public void updateProfile(Context context, String doc_name, String doc_type, String appliance_id, File file, Response.Listener<String> listener, Response.ErrorListener errorListener) {
        SimpleMultiPartRequest request = new SimpleMultiPartRequest(Request.Method.POST, "YOUR URL HERE", listener, errorListener);
//        request.setParams(data);
        mRequestQueue = RequestManager.getnstance(context);
        request.addMultipartParam("token", "text", "tdfysghfhsdfh");
        request.addMultipartParam("parameter_1", "text", doc_name);
        request.addMultipartParam("dparameter_2", "text", doc_type);
        request.addMultipartParam("parameter_3", "text", appliance_id);
            request.addFile("document_file", file.getPath());

        request.setFixedStreamingMode(true);
        mRequestQueue.add(request);
    }
}

4) और अब सेवा को हिट करने के लिए इस तरह की विधि को कॉल करें

public class Main2Activity extends AppCompatActivity implements Response.ErrorListener, Response.Listener<String>{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Button button=(Button)findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                uploadData();
            }
        });
    }

    private void uploadData() {
        WebService.getInstance().updateProfile(getActivity(), "appl_doc", "appliance", "1", mChoosenFile, this, this);
    }

    @Override
    public void onErrorResponse(VolleyError error) {

    }

    @Override
    public void onResponse(String response) {
     //Your response here 
    }
}

मुझे आपके समाधान के साथ यह त्रुटि मिल रही है: java.lang.NoSuchMethodError: कोई प्रत्यक्ष विधि <init> (ILjava / lang / String; Lcom / android / volley / Request $ प्राथमिकता; Lcom / android / volley / Response $ ErrorListener; Lcom / Android / वॉली / RetryPolicy;) वर्ग L में वी / एंड्रॉयड / वॉली / अनुरोध; या इसके सुपर क्लासेस ('com.android.volley.Request की घोषणा) /data/data/com.footballscout.app/files/instant-run/dex/slice-lice_4-classes.dex) में दिखाई देती है
SpyZip

क्या आपने कक्षाओं में सही ग्रेड और आयात की जांच की?
त्वरित शिक्षार्थी

मैंने यहाँ वर्णित एक बार और आपके उत्तर github.com/DWorkS/VolleyPlus
SpyZip

1
और उस वर्ग में अपने आयात की जाँच करें जहाँ आप कभी यू का उपयोग कर रहे हैं क्योंकि आप वॉली के लिए सही आयात का उपयोग नहीं कर रहे होंगे जैसे त्रुटि श्रोता पर इंगित कर रहा है, फिर से आयात की जाँच करें और फिर प्रोजेक्ट को साफ़ करें, धन्यवाद, अगर यू अभी भी कोई भी मिल रहा है समस्या मुझे बताएं
त्वरित शिक्षार्थी

-1

ऐसा करने का मेरा तरीका है। यह दूसरों के लिए उपयोगी हो सकता है:

private void updateType(){
    // Log.i(TAG,"updateType");
     StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {

         @Override
         public void onResponse(String response) {
             // running on main thread-------
             try {
                 JSONObject res = new JSONObject(response);
                 res.getString("result");
                 System.out.println("Response:" + res.getString("result"));

                 }else{
                     CustomTast ct=new CustomTast(context);
                     ct.showCustomAlert("Network/Server Disconnected",R.drawable.disconnect);
                 }

             } catch (Exception e) {
                 e.printStackTrace();

                 //Log.e("Response", "==> " + e.getMessage());
             }
         }
     }, new Response.ErrorListener() {
         @Override
         public void onErrorResponse(VolleyError volleyError) {
             // running on main thread-------
             VolleyLog.d(TAG, "Error: " + volleyError.getMessage());

         }
     }) {
         protected Map<String, String> getParams() {
             HashMap<String, String> hashMapParams = new HashMap<String, String>();
             hashMapParams.put("key", "value");
             hashMapParams.put("key", "value");
             hashMapParams.put("key", "value"));
             hashMapParams.put("key", "value");
             System.out.println("Hashmap:" + hashMapParams);
             return hashMapParams;
         }
     };
     AppController.getInstance().addToRequestQueue(request);

 }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.