Volley解析之表单提交篇

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

Connection: keep-alive
Content-Length: 123
X-Requested-With: ShockwaveFlash/16.0.0.296
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36
Content-Type: multipart/form-data; boundary=----------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Cookie: bdshare_firstime=1409052493497

------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1
Content-Disposition: form-data; name="position"

1425264476444
------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1
Content-Disposition: form-data; name="editorIndex"

ue_con_1425264252856
------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1
Content-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请求头,在网络请求中已经为我们封装好了;可以看到这里总共是提交了三条数据,每一条数据的格式都是一样的,所以我们只需要分析一条数据即可,这里拿最后一条数据来说,因为在所有的数据之后还有一个结尾的标志。

------------Ij5ei4KM7KM7ae0KM7cH2ae0Ij5Ef1
Content-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);
            }
        });
    }
时间: 2024-09-17 03:31:00

Volley解析之表单提交篇的相关文章

点击表单提交按钮后,显示出空白的页面(项目已经做好了,使用zf框架做的)。

问题描述 点击表单提交按钮后,显示出空白的页面(项目已经做好了,使用zf框架做的). 序号 时间 角色id 角色名 类型 物品id 已恢复时间 datas as $data):?> > hfsort[$data['nOperatorType']];?> ? 点击表单提交按钮后,显示出空白的页面(项目已经做好了,使用zf框架做的).在控制器相应的方法体中的第一行echo一串数字后测试任然是空白的,但是把action的值复制到浏览器的地址栏中直接访问时却可以看到echo出来的那串数字.有哪位

Ajax提交与传统表单提交的区别说明

  本篇文章主要是对Ajax提交与传统表单提交的区别进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助 Ajax提交是通过js来提交请求,请求与响应均由js引擎来处理,页面不会刷新,用户感觉不到实际上浏览器发出了请求.比如说我们希望网页总是显示最新的新闻,而又不想老是去点刷新按钮,我们就可以用Ajax机制来实现.网上的客服软件也是ajax请求的一个比较好的案例.传统的请求页面将实现刷新,因此局限性很大. 1.为什么用AJAX? 使用AJAX,用户对Web的体验会更"敏捷":

html+ashx 表单提交示例

 这篇文章主要介绍了html+ashx 表单提交的具体实现,需要的朋友可以参考下 1,sumbit表单提交    WebForm1.aspx源码:  代码如下: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="NETFormDemo.ashx.WebForm1" %>    <!DOCT

jquery 构造函数在表单提交过程中修改数据

  这篇文章主要介绍了jquery 构造函数在表单提交过程中修改数据的方法,十分简单实用,有需要的小伙伴可以参考下. 先贴代码 ? 1 2 3 4 5 6 7 <script type="text/javascript"> function appendText(){ var content = $("#textarea").val(); var new_content = content + "wap"; $("#text

表单提交前触发函数返回true表单才会提交

 这篇文章主要介绍了表单提交前触发函数当返回true表单才会提交的具体实现,需要的朋友可以参考下 直接看代码   代码如下: <form id="payForm" action="yeepaypay.html" target="_blank" method="post" onsubmit="return checkform();">    例子中的onsubmit函数即为表单提交前触发的函数 

ajax跨域(基础域名相同)表单提交的方法_AJAX相关

本文实例讲述了ajax跨域(基础域名相同)表单提交的方法.分享给大家供大家参考.具体如下: 1.要在做ajax提交的页面中添加如下js语句: <script type="text/javascript"> document.domain="基础域名"; </script> 2.ajax表单提交表单时可以使用一个jquery的一个表单插件jquery.form.js 使用语法如下: //fromPost为要收集数据的form表单的id $(&q

JAVA网络编程之模拟表单提交

这一篇博客是对上一篇<JAVA网络编程之获取网络资源>的扩充,这一篇将使用HttpURLConnection来模拟一个表单的提交.在B/S架构的系统中,请求时通过浏览器与服务端进行交互的,提交请求参数时使用form表单进行提交,但是有很多时候,我们需要在程序中直接调用HTTP接口,同时需要传递一些参数,那么这个时候我们就可以通过使用HttpURLConnection来模拟表单的提交过程. 首先,我们可以对请求进行封装 import java.util.ArrayList; import jav

ie-form 表单提交后的返回值 使用iframe接收 IE下老是弹出新窗口 提示保存返回的json

问题描述 form 表单提交后的返回值 使用iframe接收 IE下老是弹出新窗口 提示保存返回的json 基本代码 解决方案 ie低版本可能对json类型数据解析不支持,把返回数据的响应类型修改为 text/plain 或者 text/html 应该就可以了 解决方案二: 这里看不到代码,,使用代码片把

账号验证不通过怎么阻止表单提交js+php

问题描述 账号验证不通过怎么阻止表单提交js+php 提示: 下一步 解决方案 return false ; 解决方案二: 描述太简单吧 前台阻止:form 直接不写button和submit按钮(以前就碰到过,submit和button按钮无法用js阻止提交),form标签外写一个,用jquery form插件提交 后台:检查不通过直接exit 相关文章 php-用PHP做后台登陆界面时候所遇到的问题 ajax验证用户名是否存在,失败后组阻止表单提交 弹出框-js,jquery,表单验证 js