Android 上传文件,头像。流形式

上传头像,上传图片这个基本上都会用到。网络框架时基于volley的,但是volley又不能直接上传图片或者文件格式的文件

如果有需要的话,这里有代码可以拷走。可以自定义上传的参数,如果需要可以自定义Headers

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by gyzhong on 15/3/1.
 */
public class PostUploadRequest extends Request<String> {

    /**
     * 正确数据的时候回掉用,自己封装的回掉
     */
    private VolleyListenerInterface mListener ;
    /*请求 数据通过参数的形式传入*/
    private List mListItem ;

    private String BOUNDARY = "--------------520-13-14"; //数据分隔线
    private String MULTIPART_FORM_DATA = "multipart/form-data";

    public PostUploadRequest(String url, List listItem, VolleyListenerInterface listener) {
        super(Method.POST, url, listener.errorListener());
        this.mListener = listener ;
        setShouldCache(false);
        mListItem = listItem ;
        //设置请求的响应事件,因为文件上传需要较长的时间,所以在这里加大了,设为5秒
        setRetryPolicy(new DefaultRetryPolicy(15000, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    }


    @Override
    public Map getHeaders() throws AuthFailureError {
        HashMap localHashMap = new HashMap();
        //可以在这里添加Headers参数
        return localHashMap;
    }

    /**
     * 回调正确的数据
     * @param response The parsed response returned by
     */
    @Override
    protected void deliverResponse(String response) {
        mListener.onMySuccess(response);
    }

    @Override
    public void deliverError(VolleyError error) {
    //这是为了拿到返回的错误码,例如200,404,400等。有需要的可以用一下
        int errorNo;
        if (error != null) {
            if (error.networkResponse != null) {
                errorNo = error.networkResponse.statusCode;
            } else {
                errorNo = -1;
            }

        } else {
            errorNo = -1;

        }
        MyLog.e("errorNo" + errorNo);

        mListener.onMyError(error,errorNo);//这个是我自己对Volley封装的回掉
    }

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

    @Override
    public byte[] getBody() throws AuthFailureError {
        if (mListItem == null||mListItem.size() == 0){
            return super.getBody() ;
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
        int N = mListItem.size() ;
        FormImage formImage ;
        for (int i = 0; i < N ;i++){
            formImage = mListItem.get(i) ;
            StringBuffer sb= new StringBuffer() ;
            /*第一行*/
            //`"--" + BOUNDARY + "\r\n"`
            sb.append("--"+BOUNDARY);
            sb.append("\r\n") ;
            /*第二行*/
            //Content-Disposition: form-data; name="参数的名称"; filename="上传的文件名" + "\r\n"
            sb.append("Content-Disposition: form-data;");
            sb.append(" name=\"");
            sb.append(formImage.getName()) ;
            sb.append("\"") ;
            sb.append("; filename=\"") ;
            sb.append(formImage.getFileName()) ;
            sb.append("\"");
            sb.append("\r\n") ;
            /*第三行*/
            //Content-Type: 文件的 mime 类型 + "\r\n"
            sb.append("Content-Type: ");
            sb.append(formImage.getMime()) ;
            sb.append("\r\n") ;
            /*第四行*/
            //"\r\n"
            sb.append("\r\n") ;
            try {
                bos.write(sb.toString().getBytes("utf-8"));
                /*第五行*/
                //文件的二进制数据 + "\r\n"
                bos.write(formImage.getValue());
                bos.write("\r\n".getBytes("utf-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        /*结尾行*/
        //`"--" + BOUNDARY + "--" + "\r\n"`
        String endLine = "--" + BOUNDARY + "--" + "\r\n" ;
        try {
            bos.write(endLine.toString().getBytes("utf-8"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bos.toByteArray();
    }

    @Override
    protected Response 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));
    }


    //Content-Type: multipart/form-data; boundary=----------8888888888888
    @Override
    public String getBodyContentType() {
        return MULTIPART_FORM_DATA+"; boundary="+BOUNDARY;
    }
}

这个可以算是配置文件,里面的指我都是写死的,有需要的,自己修改呦

public class FormImage {
    //参数的名称
    private String mName ;
    //文件名
    private String mFileName ;
    //文件的 mime,需要根据文档查询
    private String mMime ;
    //需要上传的图片资源,因为这里测试为了方便起见,直接把 bigmap 传进来,真正在项目中一般不会这般做,而是把图片的路径传过来,在这里对图片进行二进制转换
    private Bitmap mBitmap ;

    public FormImage(Bitmap mBitmap) {
        this.mBitmap = mBitmap;
    }

    public String getName() {
//        return mName;
//测试,把参数名称写死
        return "file" ;
    }

    public String getFileName() {
        //测试,直接写死文件的名字
        return "test.png";
    }
    //对图片进行二进制转换
    public byte[] getValue() {
        ByteArrayOutputStream bos = new ByteArrayOutputStream() ;
        mBitmap.compress(Bitmap.CompressFormat.JPEG,80,bos) ;
        return bos.toByteArray();
    }
    //因为我知道是 png 文件,所以直接根据文档查的
    public String getMime() {
        return "image/png";
    }
}

这里是调用代码,在获取到图片以后,第一个参数需要传Bitmap过来,第二个参数是自己定义接收Volley成功失败的回掉

public static void uploadImg(Bitmap bitmap, VolleyListenerInterface listener) {
        List imageList = new ArrayList();
        imageList.add(new FormImage(bitmap));
        Request request = new PostUploadRequest(url, imageList, listener);
        MyApplication.getRequestQueue().add(request);
        /**
        *MyApplication.getRequestQueue()其实这类我写个个全局的变量
        *volleyQueue = Volley.newRequestQueue(context);
        *volleyQueue .add(request)
        */
    }

我把我自己写的鉴定回掉也附上吧。

/**
 * Volley 请求成功的回掉
 */
public abstract class VolleyListenerInterface {
    //    public Context mContext;
    public static Response.Listener mListener;
    public static Response.ErrorListener mErrorListener;

    public VolleyListenerInterface() {
//        this.mContext = context;
    }


    // 请求成功时的回调函数
    public abstract void onMySuccess(String result);

    // 请求失败时的回调函数
    public abstract void onMyError(VolleyError error, int errorNo);

    // 创建请求的事件监听
    public Response.Listener responseListener() {
        mListener = new Response.Listener() {
            @Override
            public void onResponse(String s) {

                onMySuccess(s);
            }
        };
        return mListener;
    }

    // 创建请求失败的事件监听
    public Response.ErrorListener errorListener() {
        mErrorListener = new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                int errorNo;
                if (volleyError != null) {
                    if (volleyError.networkResponse != null) {
                        errorNo = volleyError.networkResponse.statusCode;
                    } else {
                        errorNo = -1;
                    }

                } else {
                    errorNo = -1;

                }

                    onMyError(volleyError, errorNo);



            }
        };
        return mErrorListener;
    }

}

你可能感兴趣的:(android)