Volley解析之表单提交篇

来源:互联网 发布:ipadpro网络不稳定 编辑:程序博客网 时间:2024/06/14 02:29

要实现表单的提交,就要知道表单提交的数据格式是怎么样,这里我从某知名网站抓了一条数据,先来分析别人提交表单的数据格式。 
数据包:

Connection: keep-aliveContent-Length: 123X-Requested-With: ShockwaveFlash/16.0.0.296User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36Content-Type: multipart/form-data; boundary=----------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1Accept: */*Accept-Encoding: gzip, deflateAccept-Language: zh-CN,zh;q=0.8Cookie: bdshare_firstime=1409052493497------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1Content-Disposition: form-data; name="position"1425264476444------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1Content-Disposition: form-data; name="editorIndex"ue_con_1425264252856------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1Content-Disposition: form-data; name="cm"100672------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1--
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

看到上面的数据包,我们不需要全部分析,我们主要关心的是数据如何封装,因为http请求头,在网络请求中已经为我们封装好了;可以看到这里总共是提交了三条数据,每一条数据的格式都是一样的,所以我们只需要分析一条数据即可,这里拿最后一条数据来说,因为在所有的数据之后还有一个结尾的标志。

------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1Content-Disposition: form-data; name="cm"100672------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1--
  • 1
  • 2
  • 3
  • 4
  • 5

这条数据一共有四行组成,加上结尾标志共有五行 
1、第一行:

"--" + boundary + "\r\n" ;
  • 1

说明:”–”为数据开始标志,boundary为http实体头定义的边界分割线,boundary可以是任意的字符串,只要和Content-Type: multipart/form-data; boundary=———-Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1中保持一直即可,”\r\n”为回车换行; 
2、第二行:

"Content-Disposition: form-data; name="参数的名称"" + "\r\n" ;
  • 1

说明:Content-Disposition表示上传的内容特性,form-data上传内容特性为表单的形式; 
3、第三行:

"\r\n" ;
  • 1

4、说明:这是一个空行,只有一个回车换行 ; 
第四行:

"参数的值" + "\r\n" ;
  • 1

说明:每个参数都是由一个key和value组成,而这一行就是value跟回车换行符 
结尾行:

"--" + boundary + "--" + "\r\n" ;
  • 1

说明:在所有的数据结束之后,需要有这个结尾标志。 
如果有多个参数,则重复1、2、3、4,直至最后一个参数的最后加上结尾行。

参数实体类

这里对参数做一个封装,因为往往提交表单的时候,都需要提交多个参数

/** * Created by gyzhong on 15/3/2. *//*表单提交的参数*/public class FormText {    /*参数的名称*/    private String mName ;    /*参数的值*/    private String mValue ;    public FormText(String mName, String mValue) {        this.mName = mName;        this.mValue = mValue;    }    public String getName() {        return mName;    }    public String getValue() {        return mValue;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

Volley 对数据的封装

在上一篇文章中我们讲了如何定制自己的 Request,在这里同样需要用到。在定制 Request 的时候,需要重写获取实体的方法

public byte[] getBody() throws AuthFailureError {}
  • 1

把参数通过二进制的形式传给服务器,当然就不需要重写获取参数的方法

protected Map<String, String> getParams() throws AuthFailureError {}
  • 1

最核心的方法也就在getBody()中,这个方法的实现,如果对表单提交的数据格式很了解,实现起来非常简单,因为这个方法就是把参数拼接成我们所分析的数据格式;

    @Override    public byte[] getBody() throws AuthFailureError {        if (mListItem == null||mListItem.size() == 0){            return super.getBody() ;        }        ByteArrayOutputStream bos = new ByteArrayOutputStream() ;        int N = mListItem.size() ;        FormText formText ;        for (int i = 0; i < N ;i++){            formText = mListItem.get(i) ;            StringBuffer sb= new StringBuffer() ;            /*第一行:"--" + boundary + "\r\n" ;*/            sb.append("--"+BOUNDARY);            sb.append("\r\n") ;            /*第二行:"Content-Disposition: form-data; name="参数的名称"" + "\r\n" ;*/            sb.append("Content-Disposition: form-data;");            sb.append("name=\"");            sb.append(formText.getName()) ;            sb.append("\"") ;            sb.append("\r\n") ;            /*第三行:"\r\n" ;*/            sb.append("\r\n") ;            /*第四行:"参数的值" + "\r\n" ;*/            sb.append(formText.getValue()) ;            sb.append("\r\n") ;            try {                bos.write(sb.toString().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();        }        Log.v("zgy","=====formText====\n"+bos.toString()) ;        return bos.toByteArray();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

可以看到,这个方法的实现,就是对数据按照我们所分析的格式组装。 
在 Request 中还有一个关键的地方,需要在 http 头部中声明内容类型为表单数据

Content-Type: multipart/form-data; boundary=----------8888888888888
  • 1

所以的重写下面方法为

public String getBodyContentType() {        return MULTIPART_FORM_DATA+"; boundary="+BOUNDARY;    }
  • 1
  • 2
  • 3

同样,我们还是前面我们blog 中讲到的接口http://www.minongbang.com/test.php?test=minongbang来测试,所以解析数据那一块跟 前面我们将的一样,具体实现如下:

/** * Created by gyzhong on 15/3/2. */public class PostFormRequest<T> extends Request<T> {    /**     * 正确数据的时候回掉用     */    private ResponseListener mListener ;    /*用来解析 json 用的*/    private Gson mGson ;    /*在用 gson 解析 json 数据的时候,需要用到这个参数*/    private Type mClazz ;    /*请求 数据通过参数的形式传入*/    private List<FormText> mListItem ;    private String BOUNDARY = "---------8888888888888"; //数据分隔线    private String MULTIPART_FORM_DATA = "multipart/form-data";    public PostFormRequest(String url, List<FormText> listItem, Type type, ResponseListener listener) {        super(Method.POST, url, listener);        this.mListener = listener ;        mGson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create() ;        mClazz = type ;        setShouldCache(false);        mListItem = listItem ;    }    /**     * 这里开始解析数据     * @param response Response from the network     * @return     */    @Override    protected Response<T> parseNetworkResponse(NetworkResponse response) {        try {            T result ;            String jsonString =                    new String(response.data, HttpHeaderParser.parseCharset(response.headers));            Log.v("zgy", "====SearchResult===" + jsonString);            result = mGson.fromJson(jsonString,mClazz) ;            return Response.success(result,                    HttpHeaderParser.parseCacheHeaders(response));        } catch (UnsupportedEncodingException e) {            return Response.error(new ParseError(e));        }    }    /**     * 回调正确的数据     * @param response The parsed response returned by     */    @Override    protected void deliverResponse(T response) {        mListener.onResponse(response);    }    @Override    public byte[] getBody() throws AuthFailureError {        if (mListItem == null||mListItem.size() == 0){            return super.getBody() ;        }        ByteArrayOutputStream bos = new ByteArrayOutputStream() ;        int N = mListItem.size() ;        FormText formText ;        for (int i = 0; i < N ;i++){            formText = mListItem.get(i) ;            StringBuffer sb= new StringBuffer() ;            /*第一行:"--" + boundary + "\r\n" ;*/            sb.append("--"+BOUNDARY);            sb.append("\r\n") ;            /*第二行:"Content-Disposition: form-data; name="参数的名称"" + "\r\n" ;*/            sb.append("Content-Disposition: form-data;");            sb.append("name=\"");            sb.append(formText.getName()) ;            sb.append("\"") ;            sb.append("\r\n") ;            /*第三行:"\r\n" ;*/            sb.append("\r\n") ;            /*第四行:"参数的值" + "\r\n" ;*/            sb.append(formText.getValue()) ;            sb.append("\r\n") ;            try {                bos.write(sb.toString().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();        }        Log.v("zgy","=====formText====\n"+bos.toString()) ;        return bos.toByteArray();    }    /*获取内容类型,这里为表单类型*/    @Override    public String getBodyContentType() {        return MULTIPART_FORM_DATA+"; boundary="+BOUNDARY;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

表单提交接口

接口我们在上一篇博文中也做了比较详细的讲解,这里就不累赘了。

    /**     *  minong 测试post表单提交接口     * @param  value 测试数据     * @param listener 回调接口,包含错误回调和正确的数据回调     */    public static void postFormMiNongApi(String value,ResponseListener listener){        List<FormText> formTextList = new ArrayList<FormText>() ;        formTextList.add(new FormText(" test",value));        Request request = new PostFormRequest(Constant.MiNonghost,formTextList,new TypeToken<SearchResult>(){}.getType(),listener) ;        VolleyUtil.getRequestQueue().add(request) ;    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

测试

PostFormActivity.java的测试代码如下

public class PostFormActivity extends ActionBarActivity {    private ListView mListView ;    private SongAdapter mAdapter ;    private List<SongDetail> mSongList ;    private ProgressDialog mDialog ;    private View mHeaderView ;    private TextView mShowPostData ;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_post_form);        mSongList = new ArrayList<SongDetail>() ;        mListView = (ListView) findViewById(R.id.id_list_view);        mAdapter = new SongAdapter(this,mSongList) ;        mHeaderView = getLayoutInflater().inflate(R.layout.list_header_item,null) ;        mShowPostData = (TextView) mHeaderView.findViewById(R.id.id_post_data) ;        mListView.addHeaderView(mHeaderView);        mListView.setAdapter(mAdapter);        mDialog = new ProgressDialog(this) ;        mDialog.setMessage("数据提交中...");        mDialog.show() ;        /*请求网络获取数据*/        MiNongApi.postFormMiNongApi(" minongbang",new DataResponseListener<SearchResult>() {            @Override            public void onErrorResponse(VolleyError error) {                Log.v("zgy","======onErrorResponse====="+error);                mDialog.dismiss();            }            @Override            public void onResponse(SearchResult response) {                Log.v("zgy","======onResponse====="+response);                mSongList.addAll(response.getData().getInfo()) ;                mAdapter.notifyDataSetChanged();                mDialog.dismiss();            }            @Override            public void postData(String data) {                mShowPostData.setText(data);            }        });    }
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 客厅的父母乐忘记密码了怎么办 微博密码忘记了手机号也换了怎么办 想改密码旧密码忘了怎么办 商标转让转让方不配合做补证怎么办 肇事后责任方拒赔怎么办久草www 我出车祸了对方逃逸找不到人怎么办 肇事车辆怀疑是故意伤人怎么办啊 法院判的交通事故罚金没钱交怎么办 公安抓人应该行政拘留却放了怎么办 停车场把人家车刮了跑了后怕怎么办 膝盖半月板损伤可走路不疼怎么办 面试过程中遇到写的笔没水怎么办 当学生会主席底下的人不服怎么办 中班学生放学总是不写作业怎么办 妻子不想离婚主动同认婚外情怎么办 淘宝自动退款超时了卖家怎么办 征途盟战刺探自己盟的没做怎么办 被蜜蜂蛰了但一周后奇痒怎么办 热带鱼小鱼抢食大鱼吃不到怎么办 家里养的植物土壤里有虫子怎么办 哺乳期乳房有硬块乳头有白点怎么办 税务查税拿到不开票销售合同怎么办 买地皮是集体证已交钱了怎么办 word里的字体都是英文版怎么办 华为手机开机卡在菊花那里怎么办 车辆挂牌时公司名称打错了怎么办 经营异常名录查不到怎么办移除 企业被列入经营税务异常名录怎么办 手机号被别人绑定了企业微信怎么办 刚出生一天的婴儿不肯吃奶怎么办 9个月孩子不好好吃奶怎么办 孩子2个月吃奶老是呛到怎么办 孩子4个月不好好吃奶怎么办? 3个月的孩子不吃奶肚子胀怎么办 刚出生的婴儿吃完奶打嗝怎么办 宝宝刚生下来一直睡觉不吃奶怎么办 刚生下来的婴儿不吃奶怎么办 刚生下来的小猫不吃奶怎么办 刚生的小羊羔不吃奶怎么办 刚出生的婴儿不会吸奶怎么办 生完小孩七十天妈妈咳嗽怎么办