当前请求不是多部分请求 Spring Boot 和 Postman(上传 json 文件加上额外字段)

Posted

技术标签:

【中文标题】当前请求不是多部分请求 Spring Boot 和 Postman(上传 json 文件加上额外字段)【英文标题】:Current request is not a multipart request Spring Boot and Postman (Uploading json file plus extra field) 【发布时间】:2021-01-17 09:00:12 【问题描述】:

我在尝试为我的请求上传 json 文件和额外的 id 或 dto 对象时收到此 Current request is not a multipart request 错误,因为这也是填充我的数据库所必需的。

当我只发送 json 文件时,一切都上传得很好,但现在我已将 id 字段添加到相关方法和 Postman,我收到此消息并努力调试和修复它,如果我可以得到任何帮助。

这些是涉及的部分:

@Controller
@RequestMapping("/api/gatling-tool/json")
public class StatsJsonController 

@Autowired
StatsJsonService fileService;

@PostMapping(value = "/import")
public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile file, @RequestBody CategoryQueryDto categoryQueryDto) 
    String message = "";

    UUID id = categoryQueryDto.getId();

    if (StatsJsonHelper.hasJsonFormat(file)) 
        try 
            fileService.save(file, id);

            message = "Uploaded the file successfully: " + file.getOriginalFilename();
            return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
         catch (Exception e) 
            message = "Could not upload the file: " + file.getOriginalFilename() + "!";
            return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
        
    

    message = "Please upload a json file!";
    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseMessage(message));







@Service
public class StatsJsonService 

@Autowired
StatsJsonRepository repository;

public void save(MultipartFile file, UUID id) 
    StatsEntity statsEntity = StatsJsonHelper.jsonToStats(file, id);
    repository.save(statsEntity);





public class StatsJsonHelper 

public static String TYPE = "application/json";

public static boolean hasJsonFormat(MultipartFile file) 

    if (!TYPE.equals(file.getContentType())) 
        return false;
    

    return true;


public static StatsEntity jsonToStats(MultipartFile file, UUID id) 

    try 
        Gson gson = new Gson();

        File myFile = convertMultiPartToFile(file);

        BufferedReader br = new BufferedReader(new FileReader(myFile));

        Stats stats = gson.fromJson(br, Stats.class);
         StatsEntity statsEntity = new StatsEntity();
        
        statsEntity.setGroup1Count(stats.stats.group1.count);
        statsEntity.setGroup1Name(stats.stats.group1.name);
        statsEntity.setGroup1Percentage(stats.stats.group1.percentage);


        statsEntity.setId(id);

        return statsEntity;

     catch (IOException e) 
        throw new RuntimeException("fail to parse json file: " + e.getMessage());
    

非常感谢。

https://github.com/francislainy/gatling_tool_backend/pull/3/files

更新

根据@dextertron 的回答添加了更改(收到 415 不支持的媒体类型错误)

@PostMapping(value = "/import")
public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile file, @RequestBody CategoryQueryDto categoryQueryDto) 

即使我将这部分从 application/json 更改为 multiform/data,同样的错误仍然存​​在。

public static String TYPE = "multiform/data";

【问题讨论】:

【参考方案1】:

我在控制器中尝试了几种组合。

为我工作的那个看起来像这样。 基本上我们必须将两个参数都传递为@RequestParam

    @PostMapping("/import")
    public ResponseEntity<Object> uploadFile(@RequestParam("file") MultipartFile file, @RequestParam String id) 
        return null;
    

我知道你想将 CategoryQueryDto 传递为 @RequestBody 但它似乎在多部分请求中 @RequestParam@RequestBody 似乎不能一起工作。

所以你 IMO 你可以在这里做两件事:-

    如上所述设计控制器,只需将id 作为字符串发送到请求中,然后直接在fileService.save(file, id); 中使用。

    如果您仍想使用CategoryQueryDto,您可以发送此"id":"adbshdb",然后使用对象映射器将其转换为CategoryQueryDto

这就是你的控制器的样子 -

    @PostMapping("/import")
    public ResponseEntity<Object> uploadFile(@RequestParam("file") MultipartFile file, @RequestParam String categoryQueryDtoString) throws JsonProcessingException 
        ObjectMapper objectMapper = new ObjectMapper();
        CategoryQueryDto categoryQueryDto = objectMapper.readValue(categoryQueryDtoString, CategoryQueryDto.class);
// Do your file related stuff
        return ResponseEntity.ok().body(file.getOriginalFilename());
    

这就是您可以使用 postman/ARC 发送请求的方式 -

PS:不要忘记像这样设置 Content-Type 标头 -

【讨论】:

【参考方案2】:

首先,您需要将 Content-Type 标头设置为“multipart/form-data”,然后作为 form-data 中的第二个参数,使用“categoryQueryDto”作为键并添加 json 作为值('id': '随便')。

之后,将控制器中的参数注释从 @RequestPart/@RequestBody 更改为 @RequestParam。

【讨论】:

嗨@dextertron_,谢谢你的回答。您是否介意看看我在此处添加的更新以及如果正确理解建议的更改,但仍然收到 415 不支持的媒体类型错误。 还添加了我的 repo 的链接,其中包含我试图带来的更改以使此功能正常工作的 PR。 github.com/francislainy/gatling_tool_backend/pull/3/files 我已经编辑了答案,请看底部的两张截图。它们来自一个可行的解决方案,只需将其替换为您的 DTO 类并试一试。 @dextertron_ Atlesat 如果您要复制答案,请给予积分。 嘿@wak786 我没有注意到你的回答,对此感到抱歉。我没有复制它,但我会给你学分。【参考方案3】:

发布我尝试过的另一个解决方案,即将 id 附加到调用路径

@PostMapping(value = "/import/id", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile file, @PathVariable(value = "id") UUID id) 
    String message = "";

    if (StatsJsonHelper.hasJsonFormat(file)) 
        try 
            fileService.save(file, id);

            message = "Uploaded the file successfully: " + file.getOriginalFilename();
            return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
         catch (Exception e) 
            message = "Could not upload the file: " + file.getOriginalFilename() + "!";
            return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
        
    

    message = "Please upload a json file!";
    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseMessage(message));

【讨论】:

以上是关于当前请求不是多部分请求 Spring Boot 和 Postman(上传 json 文件加上额外字段)的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot REST 多部分请求(文件 + json)抛出 415 Unsupported Media Type 异常

Spring Boot + Quartz:“请求的 bean 当前正在创建中:是不是存在无法解析的循环引用?”

多部分表单数据输入 Java 模型属性未在请求类中注入元素 - Spring Boot

MultipartException:当前请求不是多部分请求

如何在 Spring Boot 中实现部分 GET 请求?

在 Spring Boot 中获取请求标头