【问题标题】:How to POST image.png with Java Spring like in Postman form-data如何在 Postman 表单数据中使用 Java Spring 发布 image.png
【发布时间】:2017-09-23 14:37:07
【问题描述】:

我正在编写一个 Java 应用程序,它将内容发布到 wordpress Rest Api。但是,我在使用 Java SpringBoot 以编程方式发布“.png”文件时遇到问题,因为我不知道如何将表单数据主体添加到 HttpEntity(body, headers);

我已经使用 Postman -> Body -> form-data ->"file":"myFile.png" 完成了这项工作 查看屏幕截图: headers in Postman here Body in Postman here

我在 Java Spring 中编写了这段代码:

private MediaResponse uploadMedia (File graphicsFile) {
    String uploadUrl =  baseUrl + mediaUrl;
    HttpHeaders headers = getHttpHeader();

    headers.add(headerKeyAuthorization, User.getInstance().getUsertoken());
    headers.add("Content-Disposition", "attachment;filename=image.png");
    headers.add("Content-Type", "image/png");

    ...

我想过做这样的事情:

Map<String, File> body = new HashMap<>();
parameters.put("file", new File("image.png"));

HttpEntity requestEntity = new HttpEntity<>(body, headers);

//not interesting in this case
//excecuteMediaRequest(uploadUrl, HttpMethod.POST, requestEntity);

将文件添加到正文中。

现在我的问题是: 我必须在标头(HttpHeaders)中设置哪些“键”:“值”对,以及如何将文件添加到正文以实现相同的 POST像 Postman 一样?

我的实际解决方案当然会产生错误:

Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [java.util.HashMap] and content type [image/png]

解决方法:

我已经通过一些解决方法和@Ajit Somans 帮助它工作。这是适用于我的场景的代码。请注意,方法 generateBytArray()executeMediaRequest() 和类 MediaResponse 是自己编写的。

/**
 * Uploads media to a rest resource.
 *
 * @param graphicsFile the media file which should be uploaded
 * @return a MediaResponse which has access to resource urls and media information.
 */
private MediaResponse uploadMedia (File graphicsFile) {
    String uploadUrl =  baseUrl + mediaUrl;
    final String filename = graphicsFile.getName();
    //create headers for form data
    HttpHeaders header = getHttpHeader();
    header.set(headerKeyAuthorization, User.getInstance().getUsertoken());
    header.set("Content-Disposition", "form-data;");

    //produces a byte array resource
    ByteArrayResource contentAsResource = new ByteArrayResource(generateBytArray(graphicsFile)){
        @Override
        public String getFilename(){
            return filename;
        }
    };

    MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
    formData.add("file", contentAsResource);
    //create request entity with header and body
    HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(formData, header);
    //executes request with in custom method.
    MediaResponse respondingObject = executeMediaRequest(uploadUrl, HttpMethod.POST, requestEntity);
    return respondingObject;
}

如您所见,我们没有设置 "Content-Type" 选项,而是将 "Content-Disposition" 设置为 "form-数据” 而不是 “附件”。关键部分是将媒体文件(.png)转换为byte[]。之后,我们生成了一个 ByteArrayResource,就像 this post 中提到的那样。至少我们只是将字节数组设置到正文中并执行对给定 url 端点的请求。

这里是把File转换成byte[]的方法:

 /**
 * generates a byte Array of a file.
 *
 * @param file the file to generate a byte array of.
 * @return byte array of the given file.
 */
private byte[] generateBytArray(File file) {
    byte[] res = new byte[0];
    try {
        //File file = fileResource.getFile();
        BufferedImage image = ImageIO.read(file);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos);
        res = baos.toByteArray();

    } catch (IOException e) {
        e.printStackTrace();
    }

    return res;
}

以及执行方法:

    /**
 * Method to execute a Request to a Rest Api where we want to upload media to.
 *
 * @param url the url endpoint of the resource, where we upload the media file.
 * @param method the http request method, which ist POST in this case.
 * @param entity the http entity where header and body are stored.
 * @return a MediaResponse which has access to resource urls and media information.
 */
private MediaResponse executeMediaRequest(String url, HttpMethod method, HttpEntity entity) {
    ParameterizedTypeReference<MediaResponse> responseType = new ParameterizedTypeReference<MediaResponse>() {};
    ResponseEntity<MediaResponse> response = template.exchange(url, method, entity,
            responseType, MediaResponse.class);

    MediaResponse responseObject = response.getBody();
    logger.info("\n ******** POST MEDIA from response with param: \n " +
                    "Post id: '{}' \n " +
                    "Post REST resource endpoint: '{}' \n" +
                    "Post Permalink '{}'\n *********",
            responseObject.getMediaID(), responseObject.getRestSelfUrl(), responseObject.getPermalink());

    return responseObject;
}

感谢@Ajit Soman

【问题讨论】:

  • 你可以尝试上传你的png图像而不在邮递员中设置content-type:image/png
  • @AjitSoman 是的,也可以。如果我像您在回答中提到的那样使用 Java 和 Spring 来做这件事,我会得到一个 Exception in thread "main" org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error。如果我以编程方式将“Content-Type”设置为“image/png”,我会收到Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [image/png] 错误。任何想法如何解决这个问题?

标签: java wordpress spring rest spring-boot


【解决方案1】:

使用LinkedMultiValueMap 代替Map 也使用FileSystemResource 代替File。您的文件上传代码可能如下所示:

    LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
    map.add("file", new FileSystemResource("FILE_LOCATION"));
    HttpHeaders headers = new HttpHeaders();
    headers.set("Content-Type", "image/png");
    .. other headers...
    HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new    HttpEntity<LinkedMultiValueMap<String, Object>>(
                        map, headers);
    RestTemplate template = new RestTemplate();
    String result = template.postForObject("FILE_UPLOAD_URL",requestEntity, String.class);
    System.out.println(result);
    return result;

【讨论】:

  • 我对此进行了测试并得到了 Exception in thread "main" org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.util.LinkedMultiValueMap] and content type [image/png] 异常,如果我将 Content-Type 设置为 application/json 也是如此。如果我不添加headers.set("Content-Type", "image/png");,我会得到500 Internal Server Error。我添加了 MessageConverters FormHttpMessageConverter MappingJackson2HttpMessageConverter 甚至会遇到 500 错误。有什么想法吗?
  • 删除此行 :headers.set("Content-Type", "image/png"); 并重试
  • 我做到了,它有帮助,谢谢。我用适合我的解决方案编辑了我的帖子。
猜你喜欢
  • 2021-07-19
  • 1970-01-01
  • 2016-11-17
  • 2020-06-02
  • 2019-11-04
  • 1970-01-01
  • 2019-09-14
  • 2017-03-29
  • 2017-02-01
相关资源
最近更新 更多