android 文件上传(POST方式模拟表单提交)

android 文件上传(POST方式模拟表单提交)

直接上代码


    /** * @category 上传文件至Server的方法 * @param uploadUrl 上传路径参数 * @param uploadFilePath 文件路径 * @author ylbf_dev */
    private void uploadFile(String uploadUrl,String uploadFilePath) {
        String end = "\r\n";
        String twoHyphens = "--";
        String boundary = "******";
        try {
            URL url = new URL(uploadUrl);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setDoInput(true);
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setUseCaches(false);
            httpURLConnection.setRequestMethod("POST");
            httpURLConnection.setRequestProperty("Connection", "Keep-Alive");
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

            DataOutputStream dos = new DataOutputStream(httpURLConnection.getOutputStream());
            dos.writeBytes(twoHyphens + boundary + end);
            dos.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\"test.jpg\"" + end);
// dos.writeBytes("Content-Disposition: form-data; name=\"file\"; filename=\""
// + uploadFilePath.substring(uploadFilePath.lastIndexOf("/") + 1) + "\"" + end);
            dos.writeBytes(end);
            // 文件通过输入流读到Java代码中-++++++++++++++++++++++++++++++`````````````````````````
            FileInputStream fis = new FileInputStream(uploadFilePath);
            byte[] buffer = new byte[8192]; // 8k
            int count = 0;
            while ((count = fis.read(buffer)) != -1) {
                dos.write(buffer, 0, count);

            }
            fis.close();
            System.out.println("file send to server............");
            dos.writeBytes(end);
            dos.writeBytes(twoHyphens + boundary + twoHyphens + end);
            dos.flush();

            // 读取服务器返回结果
            InputStream is = httpURLConnection.getInputStream();
            InputStreamReader isr = new InputStreamReader(is, "utf-8");
            BufferedReader br = new BufferedReader(isr);
            String result = br.readLine();
            mLog.d(result);
            dos.close();
            is.close();

        } catch (Exception e) {
            e.printStackTrace();
            setTitle(e.getMessage());
        }

    }

值得注意的是这其实就是模拟了表单提交, 就是把信息拼接到头里面 ,这里面的头信息一定要按照规范格式去写。

这是抓取到的头信息

POST http://127.0.0.1/upload.aspx HTTP/1.1
Connection: Keep-Alive
Charset: UTF-8
Content-Type: multipart/form-data;boundary=******
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.4; GT-I9300 Build/KTU84Q)
Host: 127.0.0.1
Accept-Encoding: gzip
Content-Length: 736640

--****** Content-Disposition: form-data; name="file"; filename="test.jpg"

关于Content-Disposition

注意这里

Content-Disposition: form-data; name="file"; filename="test.jpg"

我就遇到了不同的服务器对这里的处理识别问题,一定要写成这样 你的name 和filename按照接口要求去写,外面的双引号是必须的 虽然有些人写成了单引号 有些服务器就过去了 但是环境不一样,还是要按照规范去写。

关于boundary:

RFC文档上描述,A boundary is selected that does not occur in any of the data.意思就是选择作为boundary的数据不会出现在要上传的数据里,这一点毫无疑问,如果作为分界数据的boundary,会出现在上传的数据里,那么boundary就没有意义了~其实RCF上没有规定boundary的格式,但是大多数实现里boundary都采用了—–配合一个随机数据的方式。 我这里使用的是--******

关于multipart/form-data上传方式:

其实在封装HTTP POST上传文件的方法时,只要实现这一种即可(单个文件也可以用这种方式上传),下面上RFC上的Sample:

Content-Type: multipart/form-data, boundary=AaB03x

--AaB03x Content-Disposition: form-data; name="field1" Joe Blow --AaB03x Content-Disposition: form-data; name="pics"; filename="file1.txt" Content-Type: text/plain ... contents of file1.txt ... --AaB03x--

文件分界这里要切记切记切记(重要的事说三遍)
开始是-- + boundary

        String end = "\r\n";
        String twoHyphens = "--";
        String boundary = "******";
        dos.writeBytes(twoHyphens + boundary + end);

结束的标志是--+ boundary + --

        String end = "\r\n";
        String twoHyphens = "--";
        String boundary = "******";
        dos.writeBytes(twoHyphens + boundary + twoHyphens + end);

在每一段信息描述后要跟一个\r\n再跟文件数据,文件数据后面也要跟一个\r\n,这里也是一个关键点,其他只要按照上面的Sample去实现就好了,如果Content-Type部分不想添加根据文件后缀名填充值的话,可以直接用application/octet-stream

附录

RFC文档:http://www.ietf.org/rfc/rfc1867
Content-Type对照表:http://tool.oschina.net/commons

你可能感兴趣的:(http协议,POST模拟表单)