第三方上传文件接口调用
这里的第三方上传文件接口,是指,对方要求的参数类型是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();
}
}