通过HttpURLConnection方式实现文件上传及带参接口传输

通过HttpURLConnection方式实现文件上传及带参接口传输

方法参数:
urlStr:请求URL
strParams:字符串参数(类型为Map)
fileParams:文件参数(类型为Map)

客户端请求实例

private static final int TIME_OUT = 8 * 8000;                          //超时时间
private static final String CHARSET = "UTF-8";                         //编码格式
private static final String PREFIX = "--";                            //前缀
private static final String BOUNDARY = UUID.randomUUID().toString();  //边界标识 随机生成
private static final String CONTENT_TYPE = "multipart/form-data";     //内容类型
private static final String LINE_END = "\r\n";

public static String formUpload(String urlStr, final Map<String, String> strParams, final Map<String, File> fileParams) throws Exception{
        HttpURLConnection conn = null;
        StringBuilder response = new StringBuilder();
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setReadTimeout(TIME_OUT);
            conn.setConnectTimeout(TIME_OUT);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);//Post 请求不能使用缓存
            //设置请求头参数
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("Charset", CHARSET);
            conn.setRequestProperty("Accept-Charset", CHARSET);
            //conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8;boundary=" + BOUNDARY);
            conn.setRequestProperty("Content-Type", CONTENT_TYPE + ";charset=" + CHARSET +";boundary=" + BOUNDARY);
            /**
             * 请求体
             */
            //上传参数
            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
            //getStrParams()为一个
            if(strParams != null && !strParams.isEmpty()){
                StringBuilder strSb = new StringBuilder();
                for (Map.Entry<String, String> entry : strParams.entrySet() ){
                    strSb.append(PREFIX)
                            .append(BOUNDARY)
                            .append(LINE_END)
                            .append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END)
                            .append("Content-Type: text/plain; charset=" + CHARSET + LINE_END)
                            .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                            .append(LINE_END)// 参数头设置完以后需要两个换行,然后才是参数内容
                            .append(entry.getValue())
                            .append(LINE_END);
                }
                dos.write(strSb.toString().getBytes(CHARSET));
                dos.flush();
            }
            //文件上传
            if(fileParams != null && !fileParams.isEmpty()){
                for (Map.Entry<String, File> fileEntry: fileParams.entrySet()){
                    StringBuilder fileSb = new StringBuilder();
                    fileSb.append(PREFIX).append(BOUNDARY).append(LINE_END)
                            /**
                             * 这里重点注意: name里面的值为服务端需要的key 只有这个key 才可以得到对应的文件
                             * filename是文件的名字,包含后缀名的 比如:abc.png
                             */
                            .append("Content-Disposition: form-data; name=\"file\"; filename=\""
                                    + fileEntry.getKey() + "\"" + LINE_END)
                            .append("Content-Type: " + CONTENT_TYPE + "; charset=" + CHARSET + LINE_END) //此处的ContentType不同于 请求头 中Content-Type
                            .append("Content-Transfer-Encoding: 8bit" + LINE_END)
                            .append(LINE_END);// 参数头设置完以后需要两个换行,然后才是参数内容
                    dos.write(fileSb.toString().getBytes(CHARSET));
                    dos.flush();
                    InputStream is = new FileInputStream(fileEntry.getValue());
                    byte[] buffer = new byte[1024];
                    int len = 0;
                    while ((len = is.read(buffer)) != -1){
                        dos.write(buffer,0,len);
                    }
                    is.close();
                    dos.writeBytes(LINE_END);
                }
            }
            //请求结束标志
            String end = PREFIX + BOUNDARY + PREFIX + LINE_END;
            dos.write(end.getBytes(CHARSET));
            dos.flush();
            dos.close();
            //读取服务器返回信息
            if (conn.getResponseCode() == 200) {
                InputStream in = conn.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(in, CHARSET));
                String line = null;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        }finally {
            if (conn!=null){
                conn.disconnect();
            }
        }
        return response.toString();
    }

这里要说明一下,在测试时候字符编码都为UTF-8,但服务端一直接收中文为乱码,所以要在write的时候设置一下字符编码
dos.write(strSb.toString().getBytes(CHARSET));

服务端接收实例Controller

@RequestMapping(value = "uploadFile",method = {RequestMethod.POST})
Map<String, String> uploadFile(HttpServletRequest request, HttpServletResponse response) throws Exception{
	MultipartFile file = null;
	//获取file文件参数
	CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
   				request.getSession().getServletContext());
		// 检查form中是否有enctype="multipart/form-data"
		if (multipartResolver.isMultipart(request)) {
			// 将request变成多部分request
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator iter = multiRequest.getFileNames();
			while (iter.hasNext()) {
				file = multiRequest.getFile(iter.next().toString());
				multiRequest.getFileNames();
				if (file != null) {
					//如果存在file,直接跳出
					break;
				}
			}
		}
		//获取其他参数:
		String xxxxxx = multiRequest.getParameter("xxxxxx");
		.......
		//下方就可以写实际的业务逻辑了

代码亲测有效,希望能帮助大家!


版权声明:本文为m0_57410363原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。