Bootstrap

java调用第三方上传文件接口的几种方法


这里的第三方上传文件接口,是指,对方要求的参数类型是File;
还有其他一下字符串的参数;
主要是参看了其他的文章,简单汇总一下;看完你就比较清晰了;
第三方接口接受文件的时候,基本是与页面上传的是一致的; 也就是说,我们在后台调用接口的时候,希望是跟页面上传请求类似的实现;
在这里插入图片描述

本文重点是学习了HttpClient的使用方法;并且做了测试;
其他的工具方法仅供参考,没有测试;
完整的工具类按需参考

1.使用HttpClient的

亲测都是可以使用的;
推荐:HttpClient+MultipartEntityBuilder

1.1 在HttpClient4.3之前的用法

要求的jar:HttpClient4.2
这里有2种上传方式:
1.HttpClient+MultipartRequestEntity
2.HttpClient+MultipartEntity


	// 上传文件 HttpClient+MultipartRequestEntity
	public static String doPostFile1(String url, Map<String, String> param, File file) {
		// 创建Httpclient对象
//		CloseableHttpClient httpClient = HttpClients.createDefault();
		HttpClient httpClient = new HttpClient();
		CloseableHttpResponse response = null;
		PostMethod post = new PostMethod(url);
		String resultString = "";
		List<Part> list = new ArrayList<>();
		httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
		try {
			list.add(new FilePart("file", file));
			if (param != null) {
				for (String key : param.keySet()) {
					list.add(new StringPart(key, param.get(key), "UTF-8"));
				}
			}
			Part[] parts = list.toArray(new Part[list.size()]);
			MultipartRequestEntity entity = new MultipartRequestEntity(parts, new HttpMethodParams());
			post.setRequestEntity(entity);
			post.addRequestHeader("token", param.get("token"));
			System.out.println(entity.getContentType());
			int status  = httpClient.executeMethod(post);
			System.out.println(status);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			post.releaseConnection();
		}
		return "";
	}

	// 上传文件 HttpClient+MultipartEntity,这里需要httpmime包辅助
	public static String doPostFile1_1(String url, Map<String, String> param, File file) {
		// 创建Httpclient对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		// 处理https链接
//		if (url.startsWith("https://")) {
//			httpClient = sslClient();
//		}
		CloseableHttpResponse response = null;
		String resultString = null;
		try {
			HttpPost httppost = new HttpPost(url);
			FileBody filebody = new FileBody(file);
			MultipartEntity entity = new MultipartEntity(HttpMultipartMode.RFC6532, null, Charset.forName("UTF-8"));
			entity.addPart("file", filebody);
			// 添加其他字符串参数
			if (param != null) {
				for (String key : param.keySet()) {
					entity.addPart(key, new StringBody(param.get(key), Consts.UTF_8));
				}
			}
			//httppost.addHeader("token", param.get("token"));
			httppost.setEntity(entity);
			httppost.setConfig(getConfig());
			response = httpClient.execute(httppost);
			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return resultString;
	}

其中ContentBody的实现类如下:
在这里插入图片描述

1.2 在HttpClient4.3之后的用法

在HttpClient4.3之后,原来的上传文件方法MultipartEntity已经不建议使用,现替换成新的httpmime下面的MultipartEntityBuilder。
上传方式:HttpClient+MultipartEntityBuilder

添加文件有3种方式:其中addBinaryBody这种方式比较灵活

	builder.addBinaryBody("file", file);
	builder.addBinaryBody("file", Files.readAllBytes(file.toPath()),ContentType.APPLICATION_OCTET_STREAM,file.getName());
    //或者使用addPart 
    builder.addPart("file",new FileBody(file));

要求的jar:

   <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5</version>
        </dependency>
public static String doPostFile2(String url, Map<String, String> param, File file) {
		// 创建Httpclient对象
		CloseableHttpClient httpClient = HttpClients.createDefault();
		// 处理https链接
		if (url.startsWith("https://")) {
			httpClient = sslClient();
		}
		String resultString = "";
		CloseableHttpResponse response = null;
		HttpPost httppost = new HttpPost(url);
		try {
			// HttpMultipartMode.RFC6532参数的设定是为避免文件名为中文时乱码
			MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
			// 设置请求的编码格式
			builder.setCharset(Consts.UTF_8);
			builder.setContentType(ContentType.MULTIPART_FORM_DATA);
			// 添加文件,也可以添加字节流
//			builder.addBinaryBody("file", file);
			//或者使用字节流也行,根据具体需要使用
			builder.addBinaryBody("file", Files.readAllBytes(file.toPath()),ContentType.APPLICATION_OCTET_STREAM,file.getName());
			// 或者builder.addPart("file",new FileBody(file));
			// 添加参数
			if (param != null) {
				for (String key : param.keySet()) {
					builder.addTextBody(key, param.get(key));
				}
			}
			//httppost.addHeader("token", param.get("token"));
			HttpEntity reqEntity = builder.build();
			httppost.setEntity(reqEntity);
			// 设置超时时间
			httppost.setConfig(getConfig());
			response = httpClient.execute(httppost);
			resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				response.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return resultString;
	}


辅助方法:这个用来设置超时的;
private static RequestConfig getConfig() {
		return RequestConfig.custom().setConnectionRequestTimeout(60000).setSocketTimeout(120000)
				.setConnectTimeout(60000).build();
	}

	/**
	 * 设置SSL请求处理
	 */
	private static CloseableHttpClient sslClient() {
		try {
			SSLContext ctx = SSLContext.getInstance("TLS");
			X509TrustManager tm = new X509TrustManager() {
				@Override
				public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
						throws CertificateException {
					// TODO Auto-generated method stub

				}

				@Override
				public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1)
						throws CertificateException {
					// TODO Auto-generated method stub
				}

				@Override
				public X509Certificate[] getAcceptedIssuers() {
					// TODO Auto-generated method stub
					return null;
				}

			};
			ctx.init(null, new TrustManager[] { tm }, null);
			SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
			return HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).build();
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		} catch (KeyManagementException e) {
			throw new RuntimeException(e);
		}
	}

参考:https://www.mobibrw.com/2020/27817
https://www.e-learn.cn/content/qita/636480
https://segmentfault.com/a/1190000019961522?utm_source=tag-newest
https://www.it610.com/article/1292052792185266176.htm

2.使用MultiValueMap+RestTemplate

这个是使用spring自带的工具类实现的;我没有测试,仅了解了解
参考:https://blog.csdn.net/weixin_48027232/article/details/109569260

 /**
     * 上传名片
     *
     * @param file 文件流
     * @return 返回结果
     */
    @PostMapping("/upload_image")
    public AjaxResult uploadImage(@RequestParam("file") MultipartFile file) {
        return iApiUserCenterService.uploadImage(file);
    }
    ```
    **serviceimpl:**
    /**
     * 上传名片
     */
    @Override
    public AjaxResult uploadImage(MultipartFile file) {
        AjaxResult ajaxResult = new AjaxResult();

        try {
            MultiValueMap<String, Object> bodyMap = new LinkedMultiValueMap<>();
            bodyMap.add("file", new FileSystemResource(convert(file)));


            String url = this.url + "/image/upload";
            String res = httpPostUtils.JPost(url,file,httpSession.getAttribute("token").toString());
            if ("".equals(res) || res == null) {
                logger.info("上传名片失败,调用官网接口返回结果为空->{}", res);
                ajaxResult.put(AjaxResult.CODE_TAG, AjaxResult.Type.ERROR);
                ajaxResult.put(AjaxResult.MSG_TAG, "上传名片失败,调用官网接口返回结果为空");
                return ajaxResult;
            }
            //将返回数据转换成json
            JSONObject jsonObject = JSONObject.parseObject(res);
            String message = (jsonObject.get("msg")).toString();
            String code = (jsonObject.get("code")).toString();
            JSONObject dataObject = (JSONObject) jsonObject.get("data");
            String path = dataObject.getString("path");
            //TODO 需要将返回的图片路径进行保存
            if ("1".equals(code)) {
                ajaxResult.put(AjaxResult.CODE_TAG, AjaxResult.Type.SUCCESS);
                ajaxResult.put(AjaxResult.MSG_TAG, message);
                ajaxResult.put(AjaxResult.DATA_TAG, path);
            } else {
                ajaxResult.put(AjaxResult.CODE_TAG, AjaxResult.Type.ERROR);
                ajaxResult.put(AjaxResult.MSG_TAG, message);
            }
            logger.info("上传名片接口调用结束结束,响应结果{}", res);


        } catch (Exception e) {
            ajaxResult.put(AjaxResult.CODE_TAG, AjaxResult.Type.ERROR);
            ajaxResult.put(AjaxResult.MSG_TAG, "调用上传名片接口异常");
            logger.info("调用上传名片接口异常,错误信息{}", e.getMessage());
        }
        return ajaxResult;
    }


## 重要的util
 /**
     *
     *  发送文件MultipartFile类型的参数请求第三方接口
     * @param url  请求url
     * @param file 参数
     * @return 字符流
     * @throws IOException
     */
    public String JPost(String url, MultipartFile file, String token) throws IOException {
        MultiValueMap<String, Object> bodyMap = new LinkedMultiValueMap<>();
        bodyMap.add("file", new FileSystemResource(convert(file)));
        HttpHeaders headers = new HttpHeaders();
        headers.add("accept", "*/*");
        headers.add("connection", "Keep-Alive");
        headers.add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        headers.add("Accept-Charset", "utf-8");
        headers.add("Content-Type", "application/json; charset=utf-8");
        headers.add("token", token);
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(bodyMap, headers);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        String body = response.getBody();
        return body;
    }

    /**
     * 接收处理传过来的文件
     * @param file MultipartFile 类型的文件
     * @return
     */
    public static File convert(MultipartFile file) {
        File convFile = new File(file.getOriginalFilename());
        try {
            convFile.createNewFile();
            FileOutputStream fos = new FileOutputStream(convFile);
            fos.write(file.getBytes());
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return convFile;
    }

3.使用自带的HttpURLConnection

参考:https://blog.csdn.net/weixin_44449775/article/details/103628130
这个我也没有测试,但是其中的实现方法值得参考;比如boundary,在httplcient中,其实也是会用到的,只不过封装了,自动生成了而已;

/**
     * 上传图片
     * @param urlStr
     * @param textMap
     * @param fileMap
     * @param contentType 没有传入文件类型默认采用application/octet-stream
     * contentType非空采用filename匹配默认的图片类型
     * @return 返回response数据
     */
    @SuppressWarnings("rawtypes")
    public static String formUpload(String urlStr, Map<String, String> textMap,
                                    Map<String, String> fileMap,String contentType) {
        String res = "";
        HttpURLConnection conn = null;
        // boundary就是request头和上传文件内容的分隔符
        String BOUNDARY = "---------------------------123821742118716";
        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 iter = textMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.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 iter = fileMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.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();

                    //没有传入文件类型,同时根据文件获取不到类型,默认采用application/octet-stream
                    contentType = new MimetypesFileTypeMap().getContentType(file);
                    //contentType非空采用filename匹配默认的图片类型
                    if(!"".equals(contentType)){
                        if (filename.endsWith(".png")) {
                            contentType = "image/png";
                        }else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".jpe")) {
                            contentType = "image/jpeg";
                        }else if (filename.endsWith(".gif")) {
                            contentType = "image/gif";
                        }else if (filename.endsWith(".ico")) {
                            contentType = "image/image/x-icon";
                        }
                    }
                    if (contentType == null || "".equals(contentType)) {
                        contentType = "application/octet-stream";
                    }
                    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;
    }

4.使用OkHttpClient

参考: https://blog.csdn.net/qq_40579568/article/details/112173566
这个我也没有测试,仅供大家了解或自行测试

public static JSONObject sendPostWithFile(String requestUrl, Map<String, String> params, MultipartFile upload) {
        String responseContent  = null;
        File file = null;
        //httpclients构造post请求
        // CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            file = multipartFileToFile(upload);
            String path = file.getAbsolutePath();
            String token = params.get("access_token");
            String appid = params.get("_appid");
            String dealerid = params.get("dealerid");
            String key = params.get("key");

            OkHttpClient client = new OkHttpClient().newBuilder()
                    .build();
            RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                    .addFormDataPart("access_token",token)
                    .addFormDataPart("_appid",appid)
                    .addFormDataPart("dealerid",dealerid)
                    .addFormDataPart("key",key)
                    .addFormDataPart("imagefile",upload.getOriginalFilename(),
                            RequestBody.create(MediaType.parse("image/*"),
                                    new File(path)))
                    .addFormDataPart("serialnum","1")
                    .build();
            Request request = new Request.Builder()
                    .url(requestUrl)
                    .method("POST", body)
                    .addHeader("Content-Type", "multipart/form-data")
                    .build();
            Response response = client.newCall(request).execute();
            if (response.body() == null) {
                logger.error("接口访问异常:"+requestUrl);
                return null;
            }
            return JSONObject.parseObject(response.body().string());
        } catch (Exception e) {
            logger.error("HttpUtil=====Start");
            logger.error(e.getMessage(),e);
            logger.error("HttpUtil=====End");
        }finally {//处理结束后关闭httpclient的链接
            // try {
            //     httpClient.close();
            // } catch (IOException e) {
            //     e.printStackTrace();
            // }
            if (file != null) {
                boolean delete = file.delete();
                if (delete) {
                    logger.error("删除成功!");
                }
            }
        }
        return null;
    }


/**
	 * MultipartFile 转 File
	 *
	 * @param file
	 * @throws Exception
	 */
	public static File multipartFileToFile(MultipartFile file) throws Exception {

		File toFile = null;
		if (file.equals("") || file.getSize() <= 0) {
			file = null;
		} else {
			InputStream ins = null;
			ins = file.getInputStream();
			toFile = new File(file.getOriginalFilename());
			inputStreamToFile(ins, toFile);
			ins.close();
		}
		return toFile;
	}

	//获取流文件
	private static void inputStreamToFile(InputStream ins, File file) {
		try {
			OutputStream os = new FileOutputStream(file);
			int bytesRead = 0;
			byte[] buffer = new byte[8192];
			while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			ins.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

;