WebClient 如何发送包含字节数组的 POST 请求?
How to send a POST request that contains byte array by WebClient?
我想通过 POST 方法通过 WebClient
发送文件请求,我需要将文件作为 byte[]
发送以获得正确的响应。
我把 MultipartFile file
改成 byte[]
,然后我想我需要使用 BodyInserters
使此正文包含 byte[]
但我不知道如何制作该请求正文。
如何通过 WebClient
发送包含字节数组的 POST 请求?
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
@RestController
public class ApiController {
@PostMapping(value = "/update")
public String update(@RequestParam("file") MultipartFile file, @RequestParam("uri") String uri ) {
String result = "{error : error}";
byte[] byteArr;
BodyInserters byteArrInserter;
try {
byteArr = file.getBytes();
A? publisher = B?.C?; // I don't know what will be right for those A?, B?, C?
byteArrInserter = BodyInserters.fromDataBuffers(publisher); // In fact, I'm not sure this method will be good for this situation, either.
} catch (Exception e) {
System.out.println(e);
}
WebClient client = WebClient.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize( 1024*1024*1024 * 2)) // 2GB
.build();
try {
result = client
.post()
.uri(uri)
.body(byteArrInserter)
.retrieve().bodyToMono(String.class).block();
} catch (Exception e) {
System.out.println(e);
}
return result;
}
}
我不知道如何使用 WebClient 发送二进制内容,但还有一些其他选项。首先是 SpringBoot 自己的 RestTemplate class,它是 WebClient 的替代品。这是一篇关于它们的比较文章:Spring WebClient vs. RestTemplate。如果您希望使用绝对可以发送二进制内容的第三方 Http 客户端,您可以查看 2 个流行的选择:
最后,我编写了自己的 Http 客户端,它是 Open-source MgntUtils 库的一部分,由我编写和维护。这个 Http 客户端非常简单,但可以完成工作。我实际上正在添加允许上传二进制信息的功能。我还没有发布它,但你可以下载分支或查看我在那里的代码。分行位于 here The HttpClient class is here。请参阅第 162 行的方法 public String sendHttpRequest(String requestUrl, HttpMethod callMethod, ByteBuffer data) throws IOException
。我测试此方法的方法如下所示:
private static void testHttpClientBinaryUpload() {
try {
byte[] content = Files.readAllBytes(Paths.get("C:\Michael\Personal\pics\testPic.jpg"));
HttpClient client = new HttpClient();
Integer length = content.length;
Files.write(Paths.get("C:\Michael\tmp\testPicOrig.jpg"), content);
client.setRequestHeader("Content-Length", length.toString());
String result = client.sendHttpRequest("http://localhost:8080/upload", HttpMethod.POST, ByteBuffer.wrap(content));
System.out.println(result);
System.out.println("HTTP " + client.getLastResponseCode() + " " + client.getLastResponseMessage());
} catch (Exception e) {
System.out.println(TextUtils.getStacktrace(e, "com.mgnt."));
}
}
接收请求的服务器端 Springboot rest 控制器如下所示:
@RestController
@RequestMapping("/upload")
public class UploadTestController {
@PostMapping
public ResponseEntity<String> uploadTest(HttpServletRequest request) {
try {
String lengthStr = request.getHeader("content-length");
int length = TextUtils.parseStringToInt(lengthStr, -1);
if(length > 0) {
byte[] buff = new byte[length];
ServletInputStream sis =request.getInputStream();
int counter = 0;
while(counter < length) {
int chunkLength = sis.available();
byte[] chunk = new byte[chunkLength];
sis.read(chunk);
for(int i = counter, j= 0; i < counter + chunkLength; i++, j++) {
buff[i] = chunk[j];
}
counter += chunkLength;
if(counter < length) {
TimeUtils.sleepFor(5, TimeUnit.MILLISECONDS);
}
}
Files.write(Paths.get("C:\Michael\tmp\testPic.jpg"), buff);
}
} catch (Exception e) {
System.out.println(TextUtils.getStacktrace(e));
}
return ResponseEntity.ok("Success");
}
}
我计划在几天内发布新版本的库,该功能将包含在内。无论如何这里是 link 到 Maven Artifacts, Github and Javadoc