zoukankan      html  css  js  c++  java
  • Java使用HttpURLConnection上传文件(转)

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

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

    JSP页面:

    [html] view plain copy
     
    1. <html>  
    2.  <head>  
    3.   <meta charset="UTF-8">  
    4.   <title>TestSubmit</title>  
    5.  </head>  
    6.  <body>  
    7.   <form name="upform" action="upload.do" method="POST" enctype="multipart/form-data">  
    8.   参数<input type="text" name="username"/><br/>  
    9.   文件1<input type="file" name="file1"/><br/>  
    10.   文件2<input type="file" name="file2"/><br/>  
    11.   <input type="submit" value="Submit" /><br/>  
    12.   </form>  
    13.  </body>  
    14. </html>  

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

    [plain] view plain copy
     
    1. -----------------------------7da2e536604c8  
    2. Content-Disposition: form-data; name="username"  
    3.   
    4. hello word  
    5. -----------------------------7da2e536604c8  
    6. Content-Disposition: form-data; name="file1"; filename="D:/haha.txt"  
    7. Content-Type: text/plain  
    8.   
    9. haha  
    10. hahaha  
    11. -----------------------------7da2e536604c8  
    12. Content-Disposition: form-data; name="file2"; filename="D:/huhu.txt"  
    13. Content-Type: text/plain  
    14.   
    15. messi  
    16. huhu  
    17. -----------------------------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
     
    1. messi  
    2. huhu  

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

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

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

    [java] view plain copy
     
    1. import java.io.BufferedReader;  
    2. import java.io.DataInputStream;  
    3. import java.io.DataOutputStream;  
    4. import java.io.File;  
    5. import java.io.FileInputStream;  
    6. import java.io.InputStreamReader;  
    7. import java.io.OutputStream;  
    8. import java.net.HttpURLConnection;  
    9. import java.net.URL;  
    10. import java.util.HashMap;  
    11. import java.util.Iterator;  
    12. import java.util.Map;  
    13.   
    14. import net.sf.jmimemagic.Magic;  
    15. import net.sf.jmimemagic.MagicMatch;  
    16.   
    17. public class HttpPostUploadUtil {  
    18.   
    19.     /** 
    20.      * @param args 
    21.      */  
    22.     public static void main(String[] args) {  
    23.         String filepath = "E:\ziliao\0.jpg";  
    24.         String urlStr = "http://127.0.0.1:8080/minicms/up/up_result.jsp";  
    25.         Map<String, String> textMap = new HashMap<String, String>();  
    26.         textMap.put("name", "testname");  
    27.         Map<String, String> fileMap = new HashMap<String, String>();  
    28.         fileMap.put("userfile", filepath);  
    29.         String ret = formUpload(urlStr, textMap, fileMap);  
    30.         System.out.println(ret);  
    31.     }  
    32.   
    33.     /** 
    34.      * 上传图片 
    35.      * @param urlStr 
    36.      * @param textMap 
    37.      * @param fileMap 
    38.      * @return 
    39.      */  
    40.     public static String formUpload(String urlStr, Map<String, String> textMap, Map<String, String> fileMap) {  
    41.         String res = "";  
    42.         HttpURLConnection conn = null;  
    43.         String BOUNDARY = "---------------------------123821742118716"; //boundary就是request头和上传文件内容的分隔符    
    44.         try {  
    45.             URL url = new URL(urlStr);  
    46.             conn = (HttpURLConnection) url.openConnection();  
    47.             conn.setConnectTimeout(5000);  
    48.             conn.setReadTimeout(30000);  
    49.             conn.setDoOutput(true);  
    50.             conn.setDoInput(true);  
    51.             conn.setUseCaches(false);  
    52.             conn.setRequestMethod("POST");  
    53.             conn.setRequestProperty("Connection", "Keep-Alive");  
    54.             conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");  
    55.             conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);  
    56.   
    57.             OutputStream out = new DataOutputStream(conn.getOutputStream());  
    58.             // text    
    59.             if (textMap != null) {  
    60.                 StringBuffer strBuf = new StringBuffer();  
    61.                 Iterator<Map.Entry<String, String>> iter = textMap.entrySet().iterator();  
    62.                 while (iter.hasNext()) {  
    63.                     Map.Entry<String, String> entry = iter.next();  
    64.                     String inputName = (String) entry.getKey();  
    65.                     String inputValue = (String) entry.getValue();  
    66.                     if (inputValue == null) {  
    67.                         continue;  
    68.                     }  
    69.                     strBuf.append(" ").append("--").append(BOUNDARY).append(" ");  
    70.                     strBuf.append("Content-Disposition: form-data; name="" + inputName + "" ");  
    71.                     strBuf.append(inputValue);  
    72.                 }  
    73.                 out.write(strBuf.toString().getBytes());  
    74.             }  
    75.   
    76.             // file    
    77.             if (fileMap != null) {  
    78.                 Iterator<Map.Entry<String, String>> iter = fileMap.entrySet().iterator();  
    79.                 while (iter.hasNext()) {  
    80.                     Map.Entry<String, String> entry = iter.next();  
    81.                     String inputName = (String) entry.getKey();  
    82.                     String inputValue = (String) entry.getValue();  
    83.                     if (inputValue == null) {  
    84.                         continue;  
    85.                     }  
    86.                     File file = new File(inputValue);  
    87.                     String filename = file.getName();  
    88.                     MagicMatch match = Magic.getMagicMatch(file, false, true);  
    89.                     String contentType = match.getMimeType();  
    90.   
    91.                     StringBuffer strBuf = new StringBuffer();  
    92.                     strBuf.append(" ").append("--").append(BOUNDARY).append(" ");  
    93.                     strBuf.append("Content-Disposition: form-data; name="" + inputName + ""; filename="" + filename + "" ");  
    94.                     strBuf.append("Content-Type:" + contentType + " ");  
    95.   
    96.                     out.write(strBuf.toString().getBytes());  
    97.   
    98.                     DataInputStream in = new DataInputStream(new FileInputStream(file));  
    99.                     int bytes = 0;  
    100.                     byte[] bufferOut = new byte[1024];  
    101.                     while ((bytes = in.read(bufferOut)) != -1) {  
    102.                         out.write(bufferOut, 0, bytes);  
    103.                     }  
    104.                     in.close();  
    105.                 }  
    106.             }  
    107.   
    108.             byte[] endData = (" --" + BOUNDARY + "-- ").getBytes();  
    109.             out.write(endData);  
    110.             out.flush();  
    111.             out.close();  
    112.   
    113.             // 读取返回数据    
    114.             StringBuffer strBuf = new StringBuffer();  
    115.             BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));  
    116.             String line = null;  
    117.             while ((line = reader.readLine()) != null) {  
    118.                 strBuf.append(line).append(" ");  
    119.             }  
    120.             res = strBuf.toString();  
    121.             reader.close();  
    122.             reader = null;  
    123.         } catch (Exception e) {  
    124.             System.out.println("发送POST请求出错。" + urlStr);  
    125.             e.printStackTrace();  
    126.         } finally {  
    127.             if (conn != null) {  
    128.                 conn.disconnect();  
    129.                 conn = null;  
    130.             }  
    131.         }  
    132.         return res;  
    133.     }  
    134.   
    135. }  

    在上述代码中,关于contentType的获取方式,我在上篇文章中已经讲述过了,有兴趣的可以看看。

  • 相关阅读:
    独立安装SharePoint 2013碰到的"SDDL"问题及解决方法
    软件编程21法则
    HtmlAgilityPack 之 HtmlNode类
    SpringBoot集成Hadoop3.1.3
    win10 mysql慢查询
    Java多线程并行计算(Google的Guava使用)
    win10安装hadoop3.1.3
    mapDB的基本用法
    SpringBoot集成JMH
    mysql死锁
  • 原文地址:https://www.cnblogs.com/zhao-shan/p/9049731.html
Copyright © 2011-2022 走看看