如何使用Volley发送文件格式

时间:2018-08-31 14:25:30

标签: java android android-volley

我正在制作一个应用程序,用户可以在其中添加来自画廊的图像,从相机捕获图像或附加PDF文件,因此我想使用截击来发送文件。我编写了MultipartRequest类,可以在其中使用ByArrayOutputStream传递位图。但是现在我要发送文件。片段中有一个sendLeave(),该片段与其他参数一起发送文件。只有MultipartRequest类和SendLeave()才是与此问题相关的代码,而其他有关如何创建文件的代码。

MultipartRequest类

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;
    }

}
}

附加文档片段

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);
}

2 个答案:

答案 0 :(得分:0)

Volley不支持多段文件

但是有一个名为Volley Plus的定制凌空库,它支持多部分文件 或使用http url连接发送文件。 遵循this。 使用http url连接,您还可以轻松显示上传进度

答案 1 :(得分:0)

这是我用来上传PDF的内容,但是您可以将其用于任何文件。我使用了相同的VolleyMultipartRequest,您只需要从文件中获取数据就可以上传它。希望对您有帮助!

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;
}