Vert.x WebClient向Django REST Framework发送Multipart/form-data失败
问题排查:Vert.x客户端向Django REST Framework发送多表单数据失败
问题描述
我用Vert.x作为客户端,Django REST Framework作为服务端,尝试发送文档和表单数据。两端代码都已编写,但请求后服务端接收不到test参数,客户端返回“test attribute not found”,同时出现Netty版本格式错误。使用Postman调用该API可正常运行,需排查此问题。
服务端代码
@api_view(['POST']) @parser_classes([MultiPartParser, FormParser]) def quick_indexing(request): data = request.data print(data) # print the entire request data dictionary test_value = data.get("test") if test_value: return Response(f"test attribute value: {test_value}") else: return Response("test attribute not found")
客户端代码
Vertx vertx = Vertx.vertx(); WebClient client = WebClient.create(vertx); Buffer file = vertx.fileSystem().readFileBlocking("C:/Users/houth/CIN Hassan.pdf"); MultipartForm form = MultipartForm.create() .attribute("test", "succed") .binaryFileUpload("file", "filename", file, "Application/pdf"); // Send a POST request with the file and form data client.postAbs("http://localhost:8000/quick-indexing") .putHeader(String.valueOf(HttpHeaders.CONTENT_TYPE), "multipart/form-data") .sendMultipartForm(form, ar -> { if (ar.succeeded()) { // Handle the response HttpResponse<Buffer> response = ar.result(); System.out.println("Status code: " + response.statusCode()); System.out.println("Response body: " + response.bodyAsString()); } else { // Handle the failure Throwable cause = ar.cause(); System.err.println("Request failed: " + cause.getMessage()); } }); System.out.println("end");
客户端运行结果
end Status code: 200 Response body: "test attribute not found" [ERROR] 2023-04-08 01:39:22.881 invalid version format: <!DOCTYPE java.lang.IllegalArgumentException: invalid version format: <!DOCTYPE at io.netty.handler.codec.http.HttpVersion.<init>(HttpVersion.java:116) ~[netty-codec-http-4.1.86.Final.jar:4.1.86.Final] at io.netty.handler.codec.http.HttpVersion.valueOf(HttpVersion.java:78) ~[netty-codec-http-4.1.86.Final.jar:4.1.86.Final]
服务端运行结果
<QueryDict: {}> [08/Apr/2023 01:39:22] "POST /quick-indexing HTTP/1.1" 200 26 [08/Apr/2023 01:39:22] code 400, message Bad request syntax ('9d') [08/Apr/2023 01:39:22] "9d" 400 -
问题分析与解决方案
核心问题点
手动设置Content-Type破坏请求格式:
Vert.x的sendMultipartForm方法会自动生成带boundary的Content-Type头(格式为multipart/form-data; boundary=xxx),手动设置multipart/form-data会覆盖这个自动生成的头,导致服务端无法识别表单数据的分隔边界,最终解析出空的request.data。Netty错误根源是请求格式异常:
服务端日志中的"9d" 400 -是请求格式错误引发的后续异常,Netty的版本格式错误则是错误响应解析导致的,本质都源于请求头设置错误。MIME类型拼写不规范:
binaryFileUpload中的"Application/pdf"应改为小写的"application/pdf",虽不是参数丢失的直接原因,但符合HTTP规范。
修正后的客户端代码
Vertx vertx = Vertx.vertx(); WebClient client = WebClient.create(vertx); Buffer file = vertx.fileSystem().readFileBlocking("C:/Users/houth/CIN Hassan.pdf"); MultipartForm form = MultipartForm.create() .attribute("test", "succed") .binaryFileUpload("file", "filename", file, "application/pdf"); // Send a POST request with the file and form data client.postAbs("http://localhost:8000/quick-indexing") .sendMultipartForm(form, ar -> { if (ar.succeeded()) { // Handle the response HttpResponse<Buffer> response = ar.result(); System.out.println("Status code: " + response.statusCode()); System.out.println("Response body: " + response.bodyAsString()); } else { // Handle the failure Throwable cause = ar.cause(); System.err.println("Request failed: " + cause.getMessage()); } }); System.out.println("end");
修正说明
- 移除手动设置
Content-Type的代码,让Vert.x自动生成带boundary的正确请求头,服务端即可正常解析表单中的test参数和文件。 - 修正MIME类型大小写,符合HTTP规范。
内容的提问来源于stack exchange,提问作者Hassan Outhami
相关产品推荐
相关产品推荐

