2

I am making app in which user can attach Image from gallery, capture from camera or attach PDF file so i want to send File using volley. I wrote MultipartRequest class in which i can pass bitmap by using ByArrayOutputStream. But now i want to send File. There is an sendLeave() in fragment which Fragment which sending file with other params. Only MultipartRequest class and SendLeave() is only related code for this question but other code for how file is created.

MultipartRequest Class

public class MultipartRequest extends Request<NetworkResponse> {

private final String twoHyphens = "--";
private final String lineEnd = "\r\n";
private final String boundary = "apiclient-" + System.currentTimeMillis();

private Response.Listener<NetworkResponse> mListener;
private Response.ErrorListener mErrorListener;
private Map<String, String> mHeaders;


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

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
    return (mHeaders != null) ? mHeaders : super.getHeaders();
}

@Override
public String getBodyContentType() {
    return "multipart/form-data;boundary=" + boundary;
}

@Override
public byte[] getBody() throws AuthFailureError {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);

    try {
        // populate text payload
        Map<String, String> params = getParams();
        if (params != null && params.size() > 0) {
            textParse(dos, params, getParamsEncoding());
        }

        // populate data byte payload
        Map<String, DataPart> data = getByteData();
        if (data != null && data.size() > 0) {
            dataParse(dos, data);
        }

        // close multipart form data after text and file data
        dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        return bos.toByteArray();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * Custom method handle data payload.
 *
 * @return Map data part label with data byte
 * @throws AuthFailureError
 */
protected Map<String, DataPart> getByteData() throws AuthFailureError {
    return null;
}

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

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

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

/**
 * Parse string map into data output stream by key and value.
 *
 * @param dataOutputStream data output stream handle string parsing
 * @param params           string inputs collection
 * @param encoding         encode the inputs, default UTF-8
 * @throws IOException
 */
private void textParse(DataOutputStream dataOutputStream, Map<String, String> params, String encoding) throws IOException {
    try {
        for (Map.Entry<String, String> entry : params.entrySet()) {
            buildTextPart(dataOutputStream, entry.getKey(), entry.getValue());
        }
    } catch (UnsupportedEncodingException uee) {
        throw new RuntimeException("Encoding not supported: " + encoding, uee);
    }
}

/**
 * Parse data into data output stream.
 *
 * @param dataOutputStream data output stream handle file attachment
 * @param data             loop through data
 * @throws IOException
 */
private void dataParse(DataOutputStream dataOutputStream, Map<String, DataPart> data) throws IOException {
    for (Map.Entry<String, DataPart> entry : data.entrySet()) {
        buildDataPart(dataOutputStream, entry.getValue(), entry.getKey());
    }
}

/**
 * Write string data into header and data output stream.
 *
 * @param dataOutputStream data output stream handle string parsing
 * @param parameterName    name of input
 * @param parameterValue   value of input
 * @throws IOException
 */
private void buildTextPart(DataOutputStream dataOutputStream, String parameterName, String parameterValue) throws IOException {
    dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
    dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" + parameterName + "\"" + lineEnd);
    dataOutputStream.writeBytes(lineEnd);
    dataOutputStream.writeBytes(parameterValue + lineEnd);
}

/**
 * Write data file into header and data output stream.
 *
 * @param dataOutputStream data output stream handle data parsing
 * @param dataFile         data byte as DataPart from collection
 * @param inputName        name of data input
 * @throws IOException
 */
private void buildDataPart(DataOutputStream dataOutputStream, DataPart dataFile, String inputName) throws IOException {
    dataOutputStream.writeBytes(twoHyphens + boundary + lineEnd);
    dataOutputStream.writeBytes("Content-Disposition: form-data; name=\"" +
            inputName + "\"; filename=\"" + dataFile.getFileName() + "\"" + lineEnd);
    if (dataFile.getType() != null && !dataFile.getType().trim().isEmpty()) {
        dataOutputStream.writeBytes("Content-Type: " + dataFile.getType() + lineEnd);
    }
    dataOutputStream.writeBytes(lineEnd);

    ByteArrayInputStream fileInputStream = new ByteArrayInputStream(dataFile.getContent());
    int bytesAvailable = fileInputStream.available();

    int maxBufferSize = 1024 * 1024;
    int bufferSize = Math.min(bytesAvailable, maxBufferSize);
    byte[] buffer = new byte[bufferSize];

    int bytesRead = fileInputStream.read(buffer, 0, bufferSize);

    while (bytesRead > 0) {
        dataOutputStream.write(buffer, 0, bufferSize);
        bytesAvailable = fileInputStream.available();
        bufferSize = Math.min(bytesAvailable, maxBufferSize);
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);
    }

    dataOutputStream.writeBytes(lineEnd);
}

class DataPart {
    private String fileName;
    private byte[] content;
    private String type;

    public DataPart() {
    }

    DataPart(String name, byte[] data) {
        fileName = name;
        content = data;
    }

    String getFileName() {
        return fileName;
    }

    byte[] getContent() {
        return content;
    }

    String getType() {
        return type;
    }

}
}

AttachDocument Fragment

public class LeaveCreate extends Fragment {
File files;

@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
 btnAttach.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            final Dialog dialog = new Dialog(getActivity());
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.dialog_layout);
            dialog.show();

            Button btnGallery = (Button) dialog.findViewById(R.id.btnGallery);
            Button btnFile = (Button) dialog.findViewById(R.id.btnFile);
            Button btnCamera = (Button) dialog.findViewById(R.id.btnCamera);

            btnGallery.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dialog.dismiss();
                    Intent pickIntent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    pickIntent.setType("image/*");
                    startActivityForResult(pickIntent,1);
                }
            });

            btnFile.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dialog.dismiss();
                    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                    intent.setType("application/pdf");
                    intent.addCategory(Intent.CATEGORY_OPENABLE);

                    try {
                        startActivityForResult(Intent.createChooser(intent,"Select a File to Upload"),2);
                    }catch (android.content.ActivityNotFoundException ex){
                        Toast.makeText(getActivity(), "Please Install a File Manager",Toast.LENGTH_SHORT).show();
                    }
                }
            });

            btnCamera.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    dialog.dismiss();
                    String filename = "digimTemp.jpg";
                    ContentValues contentValues = new ContentValues();
                    contentValues.put(MediaStore.Images.Media.TITLE,filename);

                    mCapturedImageURI = getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,contentValues);

                    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT,mCapturedImageURI);
                    startActivityForResult(cameraIntent,3);
                }
            });
        }
    });


    btnSend.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {

                SendLeave();
            }
    });
    return view;
}

 @RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == Activity.RESULT_OK) {
        if (requestCode == 1) {
            if (resultCode == Activity.RESULT_OK) {
                Uri selectedImageUri = data.getData();
                String path = getRealPathFromURI(getActivity(),selectedImageUri);
                //  Toast.makeText(getBaseContext(),path,
                //          Toast.LENGTH_LONG).show();
                files = new File(path.substring(0,path.lastIndexOf("/")),path.substring(path.lastIndexOf("/"),path.length()));
                btnAttach.setText("Gallery");
                Bitmap b = null;
                try {
                    b = MediaStore.Images.Media.getBitmap(getActivity().getContentResolver(), selectedImageUri);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                Drawable d = new BitmapDrawable(getResources(), b);

                d.setBounds(0, 0, 60, 60);
                btnAttach.setCompoundDrawables(d, null, null, null);
                btnAttach.setCompoundDrawablePadding(20);
            }

        }
        else if (requestCode == 2) {
            if (resultCode == Activity.RESULT_OK) {
                Uri selectedImageUri = data.getData();
                String path = null;

                path = getPath(getActivity(),selectedImageUri);
                Toast.makeText(getActivity().getBaseContext(),path,
                        Toast.LENGTH_LONG).show();

                files = new File(path.substring(0,path.lastIndexOf("/")),path.substring(path.lastIndexOf("/"),path.length()));
                btnAttach.setText(path.substring(path.lastIndexOf("/")+1,path.length()));
            }

        }
        else if(requestCode == 3)
        {
            if (resultCode == Activity.RESULT_OK) {

                String[] projection = { MediaStore.Images.Media.DATA };
                Cursor cursor = getActivity().managedQuery(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, null, null, null);
                int column_index_data = cursor
                        .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToLast();

                String path = cursor.getString(column_index_data);

                Bitmap photo = BitmapFactory.decodeFile(path);

                // CALL THIS METHOD TO GET THE URI FROM THE BITMAP
                // Uri tempUri = getImageUri(getApplicationContext(), bitmap);

                files = new File(path.substring(0,path.lastIndexOf("/")),path.substring(path.lastIndexOf("/"),path.length()));


                if (Integer.parseInt(String.valueOf(files.length() / 1024)) > 100) {
                    //     filesize=String.valueOf(files.length()/1048576)+" MB";
                }
                btnAttach.setText("Camera");
                // attachment.setDrawableLe

                Drawable d = new BitmapDrawable(getResources(), photo);

                d.setBounds(0, 0, 60, 60);
                btnAttach.setCompoundDrawables(d, null, null, null);
                btnAttach.setCompoundDrawablePadding(20);

            }
        }
    }
}


 public void SendLeave(){
    progressDialog.show();
    MultipartRequest multipartRequest = new MultipartRequest(Request.Method.POST, SEND_LEAVE_URL, new Response.Listener<NetworkResponse>() {
        @Override
        public void onResponse(NetworkResponse response) {

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

        }
    }){
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String,String> params = new HashMap<>();
            params.put("parent_id", SharedPreferenceManager.getmInstance(getActivity()).getID());
            params.put("student_id",studentid);
            params.put("reason",txtReason.getText().toString());
            params.put("start_date",txtFromDate.getText().toString());
            params.put("end_date",txtToDate.getText().toString());

            int i=0;
            for (String temp: teacherid){
                params.put("teacher_id["+(i++)+"]", temp);
            }
            return params;
        }

        @Override
        protected Map<String, MultipartRequest.DataPart> getByteData() {
            Map<String, MultipartRequest.DataPart> params = new HashMap<>();

            params.put("file", new MultipartRequest.DataPart());
            return params;
        }

        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String,String> headers = super.getHeaders();
            if (headers == null || headers.equals(Collections.<String, String>emptyMap())){
                headers = new HashMap<String, String>();
            }
            MyApp.get().addSessionCookie(headers);
            return headers;
        }
    };
    RequestQueue queue = Volley.newRequestQueue(getContext());
    queue.add(multipartRequest);
}
Ajay Gohel
  • 243
  • 7
  • 17

2 Answers2

0

Volley doesn’t support multi part file

But there’s a customized library of volley called Volley Plus which supports multi part file Or use http url connection to send file. Follow this. Using http url connection u can also show the upload progress easily

0

This is what I used to upload a PDF, but you can use it to any file. I used the same VolleyMultipartRequest, you just have to get the data from the file to upload it. Hope it helps you!

private void uploadPDF() {
    VolleyMultipartRequest volleyMultipartRequest = new VolleyMultipartRequest(
            Request.Method.POST,
            url,
            new Response.Listener<NetworkResponse>() {
                @Override
                public void onResponse(NetworkResponse response) {
                    //Handle response
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    //Handle error
                }
            }
    ) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            Map<String, String> params = new HashMap<>();
            //Params
            return params;
        }

        @Override
        protected Map<String, DataPart> getByteData() {
            Map<String, DataPart> params = new HashMap<>();
            String pdfName = String.valueOf(System.currentTimeMillis() + ".pdf");
            params.put("pdf", new DataPart(pdfName, getFileData()));
            return params;
        }
    };

    //I used this because it was sending the file twice to the server
    volleyMultipartRequest.setRetryPolicy(
            new DefaultRetryPolicy(
                    0,
                    -1,
                    DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
            )
    );

    requestQueue.add(volleyMultipartRequest);
}

private byte[] getFileData() {
    int size = (int) pdf.length();
    byte[] bytes = new byte[size];
    byte[] tmpBuff = new byte[size];

    try (FileInputStream inputStream = new FileInputStream(pdf)) {
        int read = inputStream.read(bytes, 0, size);
        if (read < size) {
            int remain = size - read;
            while (remain > 0) {
                read = inputStream.read(tmpBuff, 0, remain);
                System.arraycopy(tmpBuff, 0, bytes, size - remain, read);
                remain -= read;
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return bytes;
}