• Java使用HttpURLConnection上传文件


    从普通Web页面上传文件非常easy。仅仅须要在form标签叫上enctype="multipart/form-data"就可以,剩余工作便都交给浏览器去完毕数据收集并发送Http请求。可是假设没有页面的话要怎么上传文件呢?

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

    JSP页面:

    <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提交的信息为:

    -----------------------------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. 第十五、十六行就是文件的内容了。如:

    messi
    huhu

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


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

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

    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("
    ").append("--").append(BOUNDARY).append("
    ");
    					strBuf.append("Content-Disposition: form-data; name="" + inputName + ""
    
    ");
    					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("
    ").append("--").append(BOUNDARY).append("
    ");
    					strBuf.append("Content-Disposition: form-data; name="" + inputName + ""; filename="" + filename + ""
    ");
    					strBuf.append("Content-Type:" + contentType + "
    
    ");
    
    					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 = ("
    --" + BOUNDARY + "--
    ").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("
    ");
    			}
    			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;
    	}
    
    }

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

    Java怎样获取Content-Type的文件类型Mime Type

  • 相关阅读:
    难点总结:Jquery动态加载数据库中的数据(解答人:郭哲 方式:讲述jquery原理及一些函数的使用方法,学会看帮助文档)
    JavaScript window.location对象
    [实用向]Win32系统直接读取登陆用户密码
    Tarjan Pascal程序
    贴nescafe 26 div2两道程序
    NOIP2012国王游戏
    NOIP2012 classroom渣线段树
    noip2012考前水的一些渣代码
    [NOIP2012]Day1完挂,回家养猪
    【凸包】含共线判定O(N^2)
  • 原文地址:https://www.cnblogs.com/yxwkf/p/5137274.html
Copyright © 2020-2023  润新知