HttpUrlConnection上传文件

从普通Web页面上传文件很简单,只需要在form标签叫上enctype=”multipart/form-data”即可,剩余工作便都交给浏览器去完成数据收集并发送Http请求。但是如果没有页面的话要怎么上传文件呢?

由于脱离了浏览器的环境,我们就要自己去完成数据的收集并发送请求,所以就很麻烦了。首先我们来写个JSP页面并看看浏览器发出的Http请求是什么样的

JSP页面:

[html] view plain copy 在CODE上查看代码片派生到我的代码片

从普通Web页面上传文件很简单,只需要在form标签叫上enctype=”multipart/form-data”即可,剩余工作便都交给浏览器去完成数据收集并发送Http请求。但是如果没有页面的话要怎么上传文件呢?

由于脱离了浏览器的环境,我们就要自己去完成数据的收集并发送请求,所以就很麻烦了。首先我们来写个JSP页面并看看浏览器发出的Http请求是什么样的

JSP页面:

[html] view plain copy 在CODE上查看代码片派生到我的代码片

<html>
 <head>
  <meta charset="UTF-8">
  <title>TestSubmit</title>
 </head>
 <body>
  <form name="upform" action="upload.do" method="POST" enctype="multipart/form-data">
  参数<input type="text" name="username"/><br/>
  文件1<input type="file" name="file1"/><br/>
  文件2<input type="file" name="file2"/><br/>
  <input type="submit" value="Submit" /><br/>
  </form>
 </body>
</html>  

假如我参数写的内容是hello word,然后二个文件是二个简单的txt文件,form提交的信息为:

[plain] view plain copy 在CODE上查看代码片派生到我的代码片

—————————–7da2e536604c8

Content-Disposition: form-data; name=”username”

hello word

—————————–7da2e536604c8

Content-Disposition: form-data; name=”file1”; filename=”D:/haha.txt”

Content-Type: text/plain

haha

hahaha

—————————–7da2e536604c8

Content-Disposition: form-data; name=”file2”; filename=”D:/huhu.txt”

Content-Type: text/plain

messi

huhu

—————————–7da2e536604c8–

研究下规律发现有如下几点特征:

1. 第一行是“—————————–7da2e536604c8”作为分隔符,然后是“/r/n”回车换行符。 这个7da2e536604c8分隔符浏览器是随机生成的。

2. 第二行是Content-Disposition: form-data; name=”username”。代表form表单的数据域,name对应页面input标签的name值。

3. 第三行是“/r/n”回车换行符。

4. 第四行是参数username的值。

5. 第五行是7da2e536604c8分隔符。

6. 从第六行到第十行和从第十二行到第十六行,分别是上传的两个文件的数据域。

7. 第十二行是Content-Disposition: form-data; name=”file2”; filename=”D:/huhu.txt”。name对应页面input标签的name值,filename对应要上传的文件名(包括路径在内)。

8. 第十三行如果是文件就有Content-Type: text/plain。这里上传的是txt文件所以是text/plain,如果上穿的是jpg图片的话就是image/jpg了,可以自己试试看看。然后就是回车换行符。

9. 第十五、十六行就是文件的内容了。如:

[plain] view plain copy 在CODE上查看代码片派生到我的代码片

messi

huhu

10. 最后一行是—————————–7da2e536604c8–。注意最后多了二个“–”,作为结束的标志。

那么我们只要模拟这个数据,并写入到Http请求中便能实现文件的上传。

其实,在我之前的文章:HttpClient使用详解 ,就已经有利用HttpClient工具包上传文件的例子,HttpClient是Apache的一个强大的模拟并发送所有Http请求的开源类库,有时间的,大家可以学习学习,但本篇文章中,并不以HttpClient为例,而是采用Java自带的HttpURLConnection实现的。

[java] view plain copy 在CODE上查看代码片派生到我的代码片

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;  

import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicMatch;  

public class HttpPostUploadUtil {  

    /**
     * @param args
     */
    public static void main(String[] args) {
        String filepath = "E:\\ziliao\\0.jpg";
        String urlStr = "http://127.0.0.1:8080/minicms/up/up_result.jsp";
        Map<String, String> textMap = new HashMap<String, String>();
        textMap.put("name", "testname");
        Map<String, String> fileMap = new HashMap<String, String>();
        fileMap.put("userfile", filepath);
        String ret = formUpload(urlStr, textMap, fileMap);
        System.out.println(ret);
    }  

    /**
     * 上传图片
     * @param urlStr
     * @param textMap
     * @param fileMap
     * @return
     */
    public static String formUpload(String urlStr, Map<String, String> textMap, Map<String, String> fileMap) {
        String res = "";
        HttpURLConnection conn = null;
        String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(30000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);  

            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // text
            if (textMap != null) {
                StringBuffer strBuf = new StringBuffer();
                Iterator<Map.Entry<String, String>> iter = textMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry<String, String> entry = iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n");
                    strBuf.append(inputValue);
                }
                out.write(strBuf.toString().getBytes());
            }  

            // file
            if (fileMap != null) {
                Iterator<Map.Entry<String, String>> iter = fileMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry<String, String> entry = iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    File file = new File(inputValue);
                    String filename = file.getName();
                    MagicMatch match = Magic.getMagicMatch(file, false, true);
                    String contentType = match.getMimeType();  

                    StringBuffer strBuf = new StringBuffer();
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"; filename=\"" + filename + "\"\r\n");
                    strBuf.append("Content-Type:" + contentType + "\r\n\r\n");  

                    out.write(strBuf.toString().getBytes());  

                    DataInputStream in = new DataInputStream(new FileInputStream(file));
                    int bytes = 0;
                    byte[] bufferOut = new byte[1024];
                    while ((bytes = in.read(bufferOut)) != -1) {
                        out.write(bufferOut, 0, bytes);
                    }
                    in.close();
                }
            }  

            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            out.write(endData);
            out.flush();
            out.close();  

            // 读取返回数据
            StringBuffer strBuf = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                strBuf.append(line).append("\n");
            }
            res = strBuf.toString();
            reader.close();
            reader = null;
        } catch (Exception e) {
            System.out.println("发送POST请求出错。" + urlStr);
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return res;
    }  

}
假如我参数写的内容是hello word,然后二个文件是二个简单的txt文件,form提交的信息为:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
-----------------------------7da2e536604c8
Content-Disposition: form-data; name="username"  

hello word
-----------------------------7da2e536604c8
Content-Disposition: form-data; name="file1"; filename="D:/haha.txt"
Content-Type: text/plain  

haha
hahaha
-----------------------------7da2e536604c8
Content-Disposition: form-data; name="file2"; filename="D:/huhu.txt"
Content-Type: text/plain  

messi
huhu
-----------------------------7da2e536604c8--
研究下规律发现有如下几点特征:
1. 第一行是“-----------------------------7da2e536604c8”作为分隔符,然后是“/r/n”回车换行符。 这个7da2e536604c8分隔符浏览器是随机生成的。
2. 第二行是Content-Disposition: form-data; name="username"。代表form表单的数据域,name对应页面input标签的name值。
3. 第三行是“/r/n”回车换行符。
4. 第四行是参数username的值。
5. 第五行是7da2e536604c8分隔符。
6. 从第六行到第十行和从第十二行到第十六行,分别是上传的两个文件的数据域。
7. 第十二行是Content-Disposition: form-data; name="file2"; filename="D:/huhu.txt"。name对应页面input标签的name值,filename对应要上传的文件名(包括路径在内)。
8. 第十三行如果是文件就有Content-Type: text/plain。这里上传的是txt文件所以是text/plain,如果上穿的是jpg图片的话就是image/jpg了,可以自己试试看看。然后就是回车换行符。
9. 第十五、十六行就是文件的内容了。如:
[plain] view plain copy 在CODE上查看代码片派生到我的代码片
messi
huhu
10. 最后一行是-----------------------------7da2e536604c8--。注意最后多了二个“--”,作为结束的标志。

那么我们只要模拟这个数据,并写入到Http请求中便能实现文件的上传。
其实,在我之前的文章:HttpClient使用详解 ,就已经有利用HttpClient工具包上传文件的例子,HttpClient是Apache的一个强大的模拟并发送所有Http请求的开源类库,有时间的,大家可以学习学习,但本篇文章中,并不以HttpClient为例,而是采用Java自带的HttpURLConnection实现的。
[java] view plain copy 在CODE上查看代码片派生到我的代码片
java```
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;  

import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicMatch;  

public class HttpPostUploadUtil {  

    /**
     * @param args
     */
    public static void main(String[] args) {
        String filepath = "E:\\ziliao\\0.jpg";
        String urlStr = "http://127.0.0.1:8080/minicms/up/up_result.jsp";
        Map<String, String> textMap = new HashMap<String, String>();
        textMap.put("name", "testname");
        Map<String, String> fileMap = new HashMap<String, String>();
        fileMap.put("userfile", filepath);
        String ret = formUpload(urlStr, textMap, fileMap);
        System.out.println(ret);
    }  

    /**
     * 上传图片
     * @param urlStr
     * @param textMap
     * @param fileMap
     * @return
     */
    public static String formUpload(String urlStr, Map<String, String> textMap, Map<String, String> fileMap) {
        String res = "";
        HttpURLConnection conn = null;
        String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(30000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);  

            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // text
            if (textMap != null) {
                StringBuffer strBuf = new StringBuffer();
                Iterator<Map.Entry<String, String>> iter = textMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry<String, String> entry = iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n");
                    strBuf.append(inputValue);
                }
                out.write(strBuf.toString().getBytes());
            }  

            // file
            if (fileMap != null) {
                Iterator<Map.Entry<String, String>> iter = fileMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry<String, String> entry = iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    File file = new File(inputValue);
                    String filename = file.getName();
                    MagicMatch match = Magic.getMagicMatch(file, false, true);
                    String contentType = match.getMimeType();  

                    StringBuffer strBuf = new StringBuffer();
                    strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"; filename=\"" + filename + "\"\r\n");
                    strBuf.append("Content-Type:" + contentType + "\r\n\r\n");  

                    out.write(strBuf.toString().getBytes());  

                    DataInputStream in = new DataInputStream(new FileInputStream(file));
                    int bytes = 0;
                    byte[] bufferOut = new byte[1024];
                    while ((bytes = in.read(bufferOut)) != -1) {
                        out.write(bufferOut, 0, bytes);
                    }
                    in.close();
                }
            }  

            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            out.write(endData);
            out.flush();
            out.close();  

            // 读取返回数据
            StringBuffer strBuf = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                strBuf.append(line).append("\n");
            }
            res = strBuf.toString();
            reader.close();
            reader = null;
        } catch (Exception e) {
            System.out.println("发送POST请求出错。" + urlStr);
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return res;
    }  

}  
时间: 2024-08-29 15:10:45

HttpUrlConnection上传文件的相关文章

Android端通过HttpURLConnection上传文件到服务器

一:实现原理 最近在做Android客户端的应用开发,涉及到要把图片上传到后台服务器中,自己选择了做Spring3 MVC HTTP API作为后台上传接口,android客户端我选择用HttpURLConnection来通过form提交文件数据实现上传功能,本来想网上搜搜拷贝一下改改代码就好啦,发现根本没有现成的例子,多数的例子都是基于HttpClient的或者是基于Base64编码以后作为字符串来传输图像数据,于是我不得不自己动手,参考了网上一些资料,最终实现基于HttpURLConnect

Android端通过HttpURLConnection上传文件到server

一:实现原理 近期在做Androidclient的应用开发,涉及到要把图片上传到后台server中.自己选择了做Spring3 MVC HTTP API作为后台上传接口,androidclient我选择用HttpURLConnection来通过form提交文件数据实现上传功能,本来想网上搜搜拷贝一下改改代码就好啦,发现根本没有现成的样例,多数的样例都是基于HttpClient的或者是基于Base64编码以后作为字符串来传输图像数据,于是我不得不自己动手.參考了网上一些资料,终于实现基于HttpU

java http工具类和HttpUrlConnection上传文件分析

利用java中的HttpUrlConnection上传文件,我们其实只要知道Http协议上传文件的标准格式.那么就可以用任何一门语言来模拟浏览器上传文件.下面有几篇文章从http协议入手介绍了java中上传文件. Java使用HttpURLConnection上传文件 使用HttpUrlConnection进行post请求上传文件 封装HttpClient4.3.x包括文件上传 使用 HttpClient 4 进行文件上传 httpclient4教程 下面分享一个自己封装的http工具类(暂不直

Java使用HttpURLConnection上传文件

从普通Web页面上传文件很简单,只需要在form标签叫上enctype="multipart/form-data"即可,剩余工作便都交给浏览器去完成数据收集并发送Http请求.但是如果没有页面的话要怎么上传文件呢? 由于脱离了浏览器的环境,我们就要自己去完成数据的收集并发送请求,所以就很麻烦了.首先我们来写个JSP页面并看看浏览器发出的Http请求是什么样的 JSP页面: <html> <head> <meta charset="UTF-8&qu

Android项目——HttpUrlConnection上传文件(图片)

UI界面设计:     由于博客发布可能附加图片,但是图片(或者任何文件)信息必须放在http请求体的正文之中,这就需要我们使用HttpUrlConnection的时候构建Http正文. 我们先来看一下Http正文格式: 1 POST /api/feed/ HTTP/1.1 2 Accept-Encoding: gzip 3 Content-Length: 225873 4 Content-Type: multipart/form-data; boundary=OCqxMF6-JxtxoMDHm

Android开发笔记(一百一十)使用http框架上传文件

HTTP上传 与文件下载相比,文件上传的场合不是很多,通常用于上传用户头像.朋友圈发布图片/视频动态等等,而且上传文件需要服务器配合,所以容易被app开发者忽略.就上传的形式来说,app一般采用http上传文件,很少用ftp上传文件. HttpURLConnection上传 很可惜Android没有提供专门的文件上传工具类,所以我们要自己写代码实现上传功能了.其实也不难,一样是按照普通网络访问的POST流程,只是要采用"multipart/form-data"方式来分段传输.另外文件上

android 使用AsyncHttpClient框架上传文件以及使用HttpURLConnection下载文件

AsyncHttpClient开源框架android-async-http还是非常方便的. AsyncHttpClient该类通经常使用在android应用程序中创建异步GET, POST, PUT和DELETE HTTP请求.请求參数通过RequestParams实例创建.响应通过重写匿名内部类 ResponseHandlerInterface的 方法处理. 1.看代码上传文件 public void uploadFile(ArrayList<String> sendFilesPath) {

【JAVA】通过HttpURLConnection 上传和下载文件(二)

HttpURLConnection文件上传 HttpURLConnection采用模拟浏览器上传的数据格式,上传给服务器 上传代码如下: 1 package com.util; 2 3 import java.io.BufferedInputStream; 4 import java.io.BufferedReader; 5 import java.io.DataOutputStream; 6 import java.io.File; 7 import java.io.FileInputStre

android 上传文件到服务器

Android客户端 package com.example.testandroid;   import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL;   import android.app.Activity; import android.app.Alert