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<FormImage> mListItem ;

    private String BOUNDARY = "--------------520-13-14"; //數據分隔線
    private String MULTIPART_FORM_DATA = "multipart/form-data";

    public PostUploadRequest(String url, List<FormImage> 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<String, String> 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<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));
    }


    //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<FormImage> imageList = new ArrayList<FormImage>();
        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<String> 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<String> responseListener() {
        mListener = new Response.Listener<String>() {
            @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;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章