Volley框架(三):使用Volley提交表单数据

来源:互联网 发布:网络控制系统的应用 编辑:程序博客网 时间:2024/06/05 21:06

在上一篇博客《Volley框架(二):使用Volley加载图片》中,我们已经将Volley加载图片的功能说完了,这篇博客我们来说一下使用Volley提交表单数据。

要提交表单数据,我们需要解决的第一个问题就是表单数据的格式是什么样子的,获取表单数据提交格式,我们可以去其他网站上抓取数据包,也可以用HTML自己写一个表单,提交一下(即使指向一个错误链接也行),然后把提交的数据抓取到就行了。

下面是我自己写的一个简单的表单,只有两个输入框,然后随意指定一个地址提交数据然后抓取到的提交的数据:

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Encoding:gzip, deflateAccept-Language:zh-CN,zh;q=0.8Content-Length:256Content-Type:multipart/form-data; boundary=----WebKitFormBoundarykR96Kta4gvMACHfqHost:www.aaa.comOrigin:nullProxy-Connection:keep-aliveUpgrade-Insecure-Requests:1User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36------WebKitFormBoundarykR96Kta4gvMACHfqContent-Disposition: form-data; name="login_username"abcde------WebKitFormBoundarykR96Kta4gvMACHfqContent-Disposition: form-data; name="login_pswd"2332525------WebKitFormBoundarykR96Kta4gvMACHfq--
看到上面的数据包,我们不需要全部分析,我们主要关心的是数据如何封装,因为http请求头,在网络请求中已经为我们封装好了;可以看到这里总共是提交了两条数据,每一条数据的格式都是一样的,所以我们只需要分析一条数据即可,这里拿第二条数据来说,因为在所有的数据之后还有一个结尾的标志。
第二条数据:
------WebKitFormBoundarykR96Kta4gvMACHfqContent-Disposition: form-data; name="login_pswd"2332525
这条数据有4行:

第一行:"--" + boundary + "\r\n"

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

第二行:Content-Disposition: form-data; name="参数的名称" + "\r\n"
说明:Content-Disposition表示上传的内容特性,form-data上传内容特性为表单的形式;
第三行:\r\n
说明:只有换行符;
第四行:2332525 + "\r\n"
说明:因为每一个参数都是有一个key和一个value组成的,在第二行的"参数的名称"就是key,第四行提交的就是value加上换行符。

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


数据格式已经弄明白了,接下来就是怎样就这个格式的数据提交到服务器了,也就是使用Volley怎样自定义提交的护具格式了,或许有朋友就会联想到在《Volley框架(一):使用Volley请求数据》这篇博客中说到的使用Volley的自定义Request了。事实也是如此,使用Volley提交表单数据,我们确实只需要自定义一个Request就可以了,但是比前面的博客中使用的自定义Request要多重写几个方法:
① 需要重写获取实体的方法
public byte[] getBody() throws AuthFailureError{}
② 在提交表单数的时候需要在 http 头部中声明内容类型为表单数据
重写下面的方法,返回声明的内容数据类型
public String getBodyContentType() {// multipart/form-data; boundary=----WebKitFormBoundarykR96Kta4gvMACHfqreturn MULTIPART_FORM_DATA + ";boundary=" + BOUNDARY;}

自定义提交表单数据的Request

public class FormRequest extends Request<String> {    private final String BOUNDARY = "------" + UUID.randomUUID().toString(); // 随机生成边界值    private final String NEW_LINE = "\r\n"; // 换行符    private final String MULTIPART_FORM_DATA = "multipart/form-data"; // 数据类型    private String charSet = "utf-8"; // 编码    private Response.Listener listener; // 监听    private Map<String, Object> params; // 需要提交的参数    public FormRequest(String url, Map<String, Object> params, Response.Listener listener, Response.ErrorListener errorListener) {        super(Method.POST, url, errorListener);        this.listener = listener;        this.params = params;    }    public FormRequest(String url, Map<String, Object> params, String charSet, Response.Listener listener, Response.ErrorListener errorListener) {        this(url, params, listener, errorListener);        this.charSet = charSet;    }    @Override    protected Response<String> parseNetworkResponse(NetworkResponse response) {        try {            return Response.success(new String(response.data, HttpHeaderParser.parseCharset(response.headers)), HttpHeaderParser.parseCacheHeaders(response));        } catch (UnsupportedEncodingException e) {            e.printStackTrace();            // 解析异常            return Response.error(new ParseError(e));        }    }    @Override    protected void deliverResponse(String response) {        listener.onResponse(response);    }    /**     * 获取实体的方法,把参数拼接成表单提交的数据格式     *     * @return     * @throws AuthFailureError     */    @Override    public byte[] getBody() throws AuthFailureError {        if (params == null || params.size() <= 0) {            return super.getBody();        }        // ------WebKitFormBoundarykR96Kta4gvMACHfq                 第一行        // Content-Disposition: form-data; name="login_username"    第二行        //                                                          第三行        // abcde                                                    第四行        // ------WebKitFormBoundarykR96Kta4gvMACHfq--               结束行        // 开始拼接数据        StringBuffer stringBuffer = new StringBuffer();        for (String key : params.keySet()) {            Object value = params.get(key);            stringBuffer.append("--" + BOUNDARY).append(NEW_LINE); // 第一行            stringBuffer.append("Content-Disposition: form-data; name=\"").append(key).append("\"").append(NEW_LINE); // 第二行            stringBuffer.append(NEW_LINE); // 第三行            stringBuffer.append(value).append(NEW_LINE); // 第四行        }        // 所有参数拼接完成,拼接结束行        stringBuffer.append("--" + BOUNDARY + "--").append(NEW_LINE);// 结束行        try {            return stringBuffer.toString().getBytes(charSet);        } catch (UnsupportedEncodingException e) {            e.printStackTrace();            // 使用默认的编码方式,Android为utf-8            return stringBuffer.toString().getBytes();        }    }    /**     * 该方法的作用:在 http 头部中声明内容类型为表单数据     *     * @return     */    @Override    public String getBodyContentType() {        // multipart/form-data; boundary=----WebKitFormBoundarykR96Kta4gvMACHfq        return MULTIPART_FORM_DATA + ";boundary=" + BOUNDARY;    }}

运行程序,得到结果如图(部分数据):


这样,我们就实现了使用Volley提交表单数据。同样我们可以进一步将代码封装,减少重复的代码。

点击下载全部封装代码。

下一篇《Volley框架(四):使用Volley上传文件》


0 0
原创粉丝点击