@Produces(MediaType.APPLICATION_JSON) //返回值类型为json
@Consumes(MediaType.APPLICATION_JSON) //参数类型为json
@Produces(MediaType.APPLICATION_OCTET_STREAM) //返回值为文件流
@Consumes(MediaType.MULTIPART_FORM_DATA + ";charset=utf-8") //表单类型,实现文件和json数据上传,加入charset设置,防止多环境可能造成的乱码
1.1java接受文件很json数据做为请求输入的写法,将参数设置为表单,从表单获取文字和文件参数,压缩流加一层压缩,返回普通文件直接往返回值写。
@POST
@Path("/Report") //路径
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM})
@Consumes(MediaType.MULTIPART_FORM_DATA + ";charset=utf-8")
@Secured(loginCheck = false)
public Response Report(FormDataMultiPart form) {
try (ByteArrayOutputStream os = new ByteArrayOutputStream();
ZipOutputStream zipOs = new ZipOutputStream(os)) {
MapParseReq mapParseReq = form.getField("meta").getValueAs(MapParseReq.class); //将json数据获取并转化为自定义对象
FormDataBodyPart bodyPart = form.getField("file"); //获取封装的文件表单对象
// 获取文件的名称
String fileName = bodyPart.getContentDisposition().getFileName();
// 获取文件的输入流
InputStream fileInputStream = bodyPart.getValueAs(InputStream.class);
// 获取文件的类型
MediaType fileType = bodyPart.getMediaType();
//得到自己的文件reportContext输入
//文件的字节数组压缩返回,key为文件名
for (Entry e : reportContext.getReportTemFiles().entrySet()) {
String filename = e.getKey();
ZipEntry entry = new ZipEntry(filename);
zipOs.putNextEntry(entry);
zipOs.write(e.getValue());
zipOs.flush();
zipOs.closeEntry();
}
zipOs.finish(); //关闭压缩流
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
String format = dateFormat.format(new Date());
//将字节流写到返回值,并设置返回头,实现自动下载
return Response.ok(new StreamingOutput() {
@Override
public void write(OutputStream output) throws IOException, WebApplicationException {
try {
output.write(os.toByteArray());
} catch (Exception ex) {
ex.printStackTrace();
} finally {
output.flush();
output.close();
}
}
}).header("Content-disposition",
"attachment;filename=" + java.net.URLEncoder.encode(format + ".zip", "UTF-8"))
.header("Cache-Control", "no-cache").build();
} catch (Exception e) {
log.error(e.getMessage());
return Response.status(500, e.getMessage()).build();
}
}
1.2前端将参数设置为的表单的写法
// 选择的文件
let file = this.file;
// 构建 multipart 请求体
let formData = new FormData();
// 文件参数
formData.set('file', file);
let data = {}; //自己的数据
formData.set('meta', new Blob([JSON.stringify(data)], {type: "application/json"}));
let service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 1000000, // request timeout
withCredentials: true,
})
service({
url: "/Report",
data: formData,
method: "POST",
responseType: "blob"
}).then(response => {
//content-type
// 根据返回的响应类型处理不同的内容
const contentType = response.headers['content-type'];
if (contentType && contentType.includes('application/json')) {
// 处理JSON响应
// 处理返回的JSON对象
this.responseData = response.data;
} else if (contentType && contentType.includes('application/octet-stream')) {
// 处理文件流响应
const file = new Blob([response.data], { type: 'application/octet-stream' });
const link = document.createElement('a');
const url = URL.createObjectURL(file);
link.href = url;
link.download = 'file.txt'; // 设置下载的文件名 let fileName = res.headers['content-disposition'].split('=')[1] 从返回值获取文件名
link.click();
URL.revokeObjectURL(url);
}
})
可以根据响应头的类型,来判断怎么处理,取出响应类型的方式const contentType = response.headers['content-type'];,取出文件名的方式let fileName = res.headers['content-disposition'].split('=')[1] 从返回值获取文件名