调用参数是文件的API(踩坑记录)

由于之前文件传输到OA采用的方式都是前端a标签在表单展示,但是发现在移动端无法展示,于是近期在调试泛微OA-E9版本的文件上传接口。在调试并封装接口的过程中遇到一些问题。

1、首先在获取了泛微OA的一些认证参数后,先在接口调用工具ApiFox上调用。

这是他的接口文档,最开始他的类型误导了我,我以为他需要的二进制文件流,然后就各种尝试失败,然后给泛微提了个工单。给的答复是在apifox调用时,用form-data的file类型。。。

2、然后在apifox就顺利调用成功了,然后我就开始封装接口。刚开始我的想法是在服务里写一个接口,直接供其他接口调用,但是牵扯到文件流的传输不太合适,就编写为一个前端调用的上传文件接口。对了其中的解析返回参数json字符串的方法还挺好用的:

ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(responseBody);
node.get("data").get("fileid").asText();
/**
	 * OA上传附件
	 * @param category 目录id
	 * @param multipartFile 文件
	 * @param userId 用户id
	 * @return 文件id
	 * @throws IOException 异常
	 */
	@GetMapping("/uploadFile2Doc")
	@ApiOperation("OA上传附件")
	public R<String> uploadFile2Doc(@RequestParam("category") String category
		,@RequestParam("multipartFile") MultipartFile multipartFile
		,@RequestParam("userId") String userId) throws IOException {
		File tempFile = null;
		try {
			// 生成一个临时文件名
			String fileName = multipartFile.getOriginalFilename();
			// 创建临时文件路径
			Path tempFilePath = Files.createTempFile(Paths.get(System.getProperty("java.io.tmpdir")),
				fileName.substring(0, fileName.indexOf('.')),
				fileName.substring(fileName.indexOf('.')));
			tempFile = tempFilePath.toFile();
			// 检查文件是否存在,如果存在则删除
			if (tempFile.exists()) {
				tempFile.delete();
			}

			// 将MultipartFile内容写入临时文件
			multipartFile.transferTo(tempFile);


			//获取接口请求头认证参数
			OaInterfaceHeaderDTO oaInterfaceHeaderDTO = oaInterfaceToken.getOaInterfaceHeaderDTO(userId);
			//E9创建OA流程接口
			String api = "/api/doc/upload/uploadFile2Doc";

			// 目标API的URL
			String url = oaInterfaceHeaderDTO.getAddress()+ "/api/doc/upload/uploadFile2Doc";

			// 准备文件和额外的表单字段
			String fileNameParam = "file"; // 文件参数名
			String textParamNameOne = "name";
			String textParamValueOne = multipartFile.getOriginalFilename(); // 文本字段值1
			String textParamNameTwo = "category";
			String textParamValueTwo = category; // 文本字段值2

			try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
				HttpPost httpPost = new HttpPost(url);

				// 添加请求头
				httpPost.setHeader("appid", oaInterfaceHeaderDTO.getAppid());
				httpPost.setHeader("token", oaInterfaceHeaderDTO.getToken()); // 注意,这个头部通常不需要手动设置,因为MultipartEntityBuilder会处理
				httpPost.setHeader("userid", oaInterfaceHeaderDTO.getUserid());


				// 构建表单实体
				HttpEntity multiPartEntity = MultipartEntityBuilder.create()
					.setMode(HttpMultipartMode.RFC6532)
					.addBinaryBody(fileNameParam, tempFile, ContentType.APPLICATION_OCTET_STREAM, multipartFile.getOriginalFilename())
					.addTextBody(textParamNameOne, textParamValueOne, ContentType.TEXT_PLAIN)
					.addTextBody(textParamNameTwo, textParamValueTwo, ContentType.create("text/plain", StandardCharsets.UTF_8))
					.build();

				httpPost.setEntity(multiPartEntity);

				// 发送请求并获取响应
				try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
					System.out.println("Response Status Code: " + response.getStatusLine().getStatusCode());

					// 处理响应实体(如果需要)
					HttpEntity responseEntity = response.getEntity();
					if (responseEntity != null) {
						String responseBody = EntityUtils.toString(responseEntity, StandardCharsets.UTF_8);
						ObjectMapper mapper = new ObjectMapper();
						JsonNode node = mapper.readTree(responseBody);
						return R.data(node.get("data").get("fileid").asText());
					}
				}
			}
		} catch (IOException e) {
			// 如果在转换过程中出现异常,删除已创建的临时文件
			if (tempFile != null) {
				tempFile.delete();
			}
			// 处理可能的I/O异常
			throw new RuntimeException("Failed to convert MultipartFile to File", e);
		} finally {
			// 删除临时文件
			if (tempFile != null) {
				tempFile.delete();
			}
		}
		return R.data("上传失败!");
	}

3、大概的处理思路你们可以参考一下。在测试的时候,接口调用成功,但是发现一个问题,就是文件名的中文会乱码。之后排查问题发现是在上传的时候造成的乱码,以及逐步调试,锁定了问题。之前默认设置为BROWSER_COMPATIBLE。修改为RFC6532,就解决了乱码问题。

4、后面去了解了下这两种模式:

技术领域不同:RFC6532关注的是电子邮件地址的国际化,而BROWSER_COMPATIBLE关注的是Web上传请求的兼容性。


应用场景不同:一个是电子邮件通信的标准,另一个是Web通信中文件上传的兼容性模式。


目的不同:RFC6532旨在支持非ASCII字符的电子邮件地址,而BROWSER_COMPATIBLE旨在保证上传请求能被广泛接受,特别是在老式或兼容性要求高的Web服务器上。

了解下来,其实一般还是采用BROWSER_COMPATIBLE这种模式,在这种模式下保持编码的一致性,但是由于时间原因,我决定采用RFC6532解决问题,希望有缘人在正确处理这种问题后,可以答疑一下。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值