springboot服务间接口调用很简单,但是关于调用接口上传文件经常走弯路,故此总结一下:
负责上传文件的服务A():
@RequestMapping(value="/loadToRepository", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Object loadImageToRepository (@RequestPart(value = "file") MultipartFile file) {
logger.info("DockerUtils loadImageToRepository2 begin");
try {
logger.info("docker镜像名称" + file.getOriginalFilename());
//由于文件可能过大,导致页面响应超时,故此处采用线程方式上传
Thread uploadThread = new UploadThread(dockerHost, dockerUserName, dockerPassword, file.getInputStream());
uploadThread.start();
} catch (IOException e) {
return ResultUtil.error(400, "获取文件流失败");
}
return ResultUtil.success("上传结束,正在同步至镜像仓库");
}
public class UploadThread extends Thread {
private final static Logger logger = LoggerFactory.getLogger(UploadThread.class);
private String dockerHost;
private String dockerUserName;
private String dockerPassword;
private InputStream inputStream;
public UploadThread(String dockerHost, String dockerUserName, String dockerPassword, InputStream inputStream) {
super();
this.dockerHost = dockerHost;
this.dockerUserName = dockerUserName;
this.dockerPassword = dockerPassword;
this.inputStream = inputStream;
}
@Override
public void run() {
long beginTime = System.currentTimeMillis();
if (StringUtils.isEmpty(dockerUserName)) {
dockerUserName = null;
}
if (StringUtils.isEmpty(dockerPassword)) {
dockerPassword = null;
}
logger.info("dockerHost = " + dockerHost);
logger.info("dockerUserName = " + dockerUserName);
logger.info("dockerPassword = " + dockerPassword);
DockerClientConfig dockerClientConfig = DefaultDockerClientConfig.createDefaultConfigBuilder()
.withRegistryUsername(dockerUserName)
.withRegistryPassword(dockerPassword)
.withDockerConfig(null)
.withDockerHost(dockerHost).build();
DockerCmdExecFactory dockerCmdExecFactory = new JerseyDockerCmdExecFactory()
.withReadTimeout(60000)
.withConnectTimeout(1000)
.withMaxTotalConnections(100)
.withMaxPerRouteConnections(10);
DockerClient dockerClient = DockerClientBuilder.getInstance(dockerClientConfig).withDockerCmdExecFactory(dockerCmdExecFactory).build();
logger.info("docker versin is " + dockerClient.versionCmd().exec().getVersion().toString());
// final Iterator<String> iterator = request.getFileNames();
MultipartFile multipartFile = null;
// while (iterator.hasNext()) {
// multipartFile = request.getFile(iterator.next());
// LoadImageCmd loadImageCmd = dockerClient.loadImageCmd(new FileInputStream(new File("C://Users//Administrator//Desktop//docker-java-api//mysql.tar")));
try {
LoadImageCmd loadImageCmd = dockerClient.loadImageCmd(inputStream);
loadImageCmd.exec();
} catch (Exception e) {
e.printStackTrace();
logger.error("上传Docker镜像失败");
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
logger.error("文件流关闭失败");
}
}
}
// }
long endTime = System.currentTimeMillis();
logger.info("上传Docker镜像结束,用时:" + (endTime - beginTime) + "ms");
}
}
消费服务A上传文件接口的服务B:
public Map<String, Object> uploadInstall(final HttpServletRequest httpServletRequest, final String code) {
logger.info("准备上传镜像至镜像仓库, tempPath=" + tempPath);
new HttpClientUtils().uploadFile(dockerURL, file, tempPath);
return resultMap;
}
public boolean uploadFile (String url, MultipartFile file, String tempPath) {
HttpHeaders headers = new HttpHeaders();
String tempFileName = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
logger.info("tempPath = " + tempPath);
String tempFilePath = tempPath + tempFileName;
File tempFile = new File(tempFilePath);
try {
file.transferTo(tempFile);
FileSystemResource fileSystemResource = new FileSystemResource(tempFilePath);
logger.info("临时文件路径:" + fileSystemResource.getPath());
MediaType type = MediaType.parseMediaType("multipart/form-data; charset=UTF-8");
headers.setContentType(type);
String cd = "filename=\"" + file.getOriginalFilename() + "\"";
headers.add("Content-Disposition", cd);
MultiValueMap<String, Object> form = new LinkedMultiValueMap<String, Object>();
form.add("file", fileSystemResource);
final RestTemplate restTemplate = new RestTemplate();
Object recv = restTemplate.postForEntity(url, form, Object.class);
try {
logger.info("调用上传镜像包接口返回的数据:" + recv.toString());
tempFile.delete();
} catch (Exception e) {
e.printStackTrace();
}
} catch (IllegalStateException e) {
logger.error("httpclient close failed", e);
} catch (IOException e) {
logger.error("httpclient close failed", e);
}
return true;
}