Spring Boot:发布和处理具有多个主体部分的多部分/表单数据请求

时间:2019-11-18 15:34:59

标签: spring spring-boot post multipartform-data resttemplate

我具有以下处理multipart / form-data请求的端点:

    @RequestMapping(value = "/test", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity<Response> handleRequest(
            @RequestPart(value = "image") MultipartFile image,
            @RequestPart(value = "data") Request request, HttpServletRequest request) throws IOException {
    }

当我使用IDEA rest客户端对其进行测试时,将按预期达到端点:

POST http://myUrl/test
Accept: */*
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=xxxx
Authorization: Basic username pass

--xxxx
Content-Disposition: form-data; name="image"; filename="image.jpg"
Content-Type: image/jpg

< C:\pathToImage\image.jpg
--xxxx
Content-Disposition: form-data; name="data"
Content-Type: application/json

{
"firstName":"John",
"lastName":"Doe"
}
--xxxx

但是,当我尝试通过Spring RestTemplate到达此端点时,观察到400响应和以下错误: Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'image' is not present]

我用于发布请求的代码如下:

public Response test(final byte[] image, MediaType imageMimeType, final Request request) {
        String url = "http://myUrl/test";
        HttpHeaders headers = HeaderUtils.headerBasicAuth("username", "pass");
        headers.set(HttpHeaders.ACCEPT,MediaType.APPLICATION_JSON_VALUE);
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("image", new InputStreamResource(new ByteArrayInputStream(image)));
        map.add("data", request.toJson());
        HttpEntity<?> requestEntity = new HttpEntity<>(map, headers);
        ResponseEntity<Response> result = template.exchange(url, HttpMethod.POST, requestEntity, Response.class);
        return result.getBody();
    }

Request类的大概代码如下:

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.io.IOException;
import java.io.Serializable;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.json.JSONObject;

@AllArgsConstructor(access = AccessLevel.PUBLIC)
@Getter
@JsonInclude(Include.NON_NULL)
public final class VerifyRequest implements Cloneable, Serializable {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private final String firstName;
    private final String lastName;

    public JSONObject toJson() {
        String json;
        try {
            json = OBJECT_MAPPER.writeValueAsString(this);
        } catch (JsonProcessingException var3) {
            throw new IllegalStateException(var3);
        }

        return new JSONObject(json);
    }
    ....
}

任何建议如何发布此类请求?

1 个答案:

答案 0 :(得分:0)

您收到该错误,因为您没有在 MultiValueMap 中为图像字段使用有效的对象。通常,您将使用 FileSystemResource 从磁盘加载映像,其中有很多示例。

但是,如果您仍然想从字节数组中获取它,则可以使用 ByteArrayResource 覆盖getFilename(),这在控制器端是必需的。所以代替:

map.add("image", new InputStreamResource(new ByteArrayInputStream(image)));

只放:

ByteArrayResource byteArrayResource = new ByteArrayResource(image) {
    @Override
    public String getFilename() {
        return "image.jpg";
    }
};
map.add("image", byteArrayResource);