业务场景
有这么种业务开发场景,文件的上传是无需客户直接操作的,而是后端业务先将文件上传到文件服务器上,而后将文件存储信息返回给前端展示即可, 再进行其他业务操作!
本次代码演示场景,使用java-poi
将文档真实数据渲染出来, 并将结果文件上传到文件服务器上,随后返回文件存储信息,前端可通过返回信息进行在线编辑文档。
API技术选型
RestTemplate,OkHttpClient......
本次演示使用后者:OkHttpClient
其它像底层HttpClient也是没问题的。前者封装后,代码更简洁
核心说明
- 获取poi处理完的工作簿/文件对象, 将该对象写入输出流
FileOutputStream
中,如: WorkBook/XWPFTemplate - 建立临时文件(后续删掉), 然后获取该文件输入流
FileInputStream
- 使用
OkHttpClient
技术进行文件上传(携带token) - 调用成功,
解析返回值
,封装后并返回给前端
代码展示
一、全局变量声明
@Resource
private HttpServletRequest httpServletRequest;
private static final String PART_NAME = "file";
private static final String ATTACH_TYPE = "application/octet-stream";
private static final String METHOD_TYPE = "POST";
private static final String TOKEN_KEY = "token";
二、获取临时文件
/**
* @Description: 准备临时文件
* @Params: [fileName->文件名称, xwpfTemplate->poi处理后的文件对象]
*/
private SysFileVo wordDataRendering(String fileName, XWPFTemplate xwpfTemplate) {
// 变量声明
File tempFile = null;
FileOutputStream fileOutputStream = null;
FileInputStream fileInputStream = null;
try {
// 构建可上传文件流
tempFile = new File(systemConfig.getFilePath() + fileName);
fileOutputStream = new FileOutputStream(tempFile);
xwpfTemplate.write(fileOutputStream);
fileInputStream = new FileInputStream(tempFile);
return uploadFile(fileName, fileInputStream);
} catch (IOException ioException) {
throw new IllegalArgumentException("文件流操作异常!");
} finally {
// 删除临时建立的文件
if (null != tempFile && tempFile.exists()) {
tempFile.delete();
}
close(fileInputStream, fileOutputStream, xwpfTemplate);
}
}
/**
* @Description: IO流的关闭
* @Params: [closeableList]
*/
public void close(Closeable... closeableList) {
for (Closeable closeable : closeableList) {
try {
if (closeable != null) {
closeable.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、服务间调用-文件上传
/**
* @Description: 实现服务间调用---文件上传
* @Params: [fileName, fileInputStream]
*/
public SysFileVo uploadFile(String fileName, FileInputStream fileInputStream) {
// 获取token数据
String token = httpServletRequest.getHeader(CasPrehandlerConfig.TOKEN_KEY);
try {
// 构建上传文件内容
byte[] byteFileContent = new byte[fileInputStream.available()];
fileInputStream.read(byteFileContent);
OkHttpClient client = new OkHttpClient().newBuilder()
.build();
okhttp3.RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart(PART_NAME, fileName,
okhttp3.RequestBody.create(MediaType.parse(ATTACH_TYPE), byteFileContent))
.build();
// 上线使用url: systemConfig.getUploadAddress()
Request request = new Request.Builder()
.url("http://本地IP:3399/fileSupport/upload")
.method(METHOD_TYPE, requestBody)
.addHeader(TOKEN_KEY, token)
.build();
Response response = client.newCall(request).execute();
// 响应内容数据解析
String responseBodyJson = StrUtil.EMPTY;
if (null != response.body()) {
responseBodyJson = response.body().string();
}
R responseData = JSONObject.parseObject(responseBodyJson, R.class);
if (null != responseData && responseData.getState() == 200) {
JSONObject jsonObject = (JSONObject) responseData.getData();
return jsonObject.toJavaObject(SysFileVo.class);
} else if (null != responseData && responseData.getState() == 500) {
throw new IllegalArgumentException("文件上传失败!");
} else {
return null;
}
} catch (IOException e) {
throw new IllegalArgumentException("文件流操作异常!");
}
}
后续说明
接口返回信息中含有文件下载地址,供后续业务操作,如下载文件、在线编辑。