首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >com.google.cloud.functions.HttpRequest实例不支持同一字段中有多于一个文件的表单数据。

com.google.cloud.functions.HttpRequest实例不支持同一字段中有多于一个文件的表单数据。
EN

Stack Overflow用户
提问于 2022-01-23 20:34:12
回答 1查看 253关注 0票数 0

我正在创建一个gcloud http云函数,它必须接收一个带有"medias“字段的” form -data“表单,该字段最多可以包含3个文件,下面是基本代码:

gcloud Java函数:

代码语言:javascript
复制
package functions;

import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import java.io.BufferedWriter;
import java.io.IOException;

public class HelloWorld implements HttpFunction {
  @Override
  public void service(HttpRequest request, HttpResponse response)
      throws IOException {
    var parts = request.getParts();

    parts.forEach(
            (e1, e2) -> {
                System.out.println(e1);
                System.out.println(e2.getFileName().get());
            });


  }
}

我的简单要求是:

代码语言:javascript
复制
curl --location --request POST 'http://localhost:8080/' \
--form 'medias=@"/file1.jpeg"' \
--form 'medias=@"/file2.jpeg"'

奇怪的是,"request.getParts();"返回一个"Map<String, HttpPart>",因此我不知道如何检索同一个提交参数的多个文件。在调试过程中,我得到了一个不错的结果:

“com.google.cloud.functions.invoker.http.HttpRequestImpl$HttpPartImpl@49e848cf :重复的关键媒体(尝试合并值java.lang.IllegalStateException)

( com.google.cloud.functions.invoker.http .HttpRequestImpl$HttpPartImpl@6d5d7015)“

通过将"Springboot“指定为参数,相同的查询可以正常工作:

代码语言:javascript
复制
@RequestParam(value = "medias", required = false) MultipartFile[] medias

那么你认为这是一个有这种依赖性的bug吗?

代码语言:javascript
复制
<dependency>
    <groupId>com.google.cloud.functions</groupId>
    <artifactId>functions-framework-api</artifactId>
    <version>1.0.4</version>
    <scope>provided</scope>
</dependency>
EN

回答 1

Stack Overflow用户

发布于 2022-01-26 16:46:54

正如这个GCP 文档中所提到的,您可以使用下面的示例代码来处理多部分/表单数据内容类型的数据。

代码语言:javascript
复制
for (HttpRequest.HttpPart httpPart : request.getParts().values()) {
      String filename = httpPart.getFileName().orElse(null);
      if (filename == null) {
        continue;
      }
      
      //do something here
}

我使用您的场景进行了一些测试,并尝试使用java.util.stream.Collectors操作getParts()方法,以想出类似于Map<String, List<HttpPart>>的解决方案,但失败了。似乎不可能对每个表单数据使用相同的参数键。

我还检查了HttpRequest.getParts()方法的源代码,发现它有自己的方式从表单收集流--当每个数据只有一个键时,表单数据失败,如下所示:

代码语言:javascript
复制
public Map<String, HttpRequest.HttpPart> getParts() {
    String contentType = this.request.getContentType();
    if (contentType == null || this.request.getContentType().startsWith("multipart/form-data"))
        throw new IllegalStateException("Content-Type must be multipart/form-data: " + contentType);
     try {
         return (Map<String, HttpRequest.HttpPart>)this.request.getParts().stream().collect(Collectors.toMap(Part::getName, x -> new HttpPartImpl(x)));
     } catch (IOException e) {
         throw new UncheckedIOException(e);
     } catch (ServletException e) {
         throw new RuntimeException(e.getMessage(), e);
     }
}

最后,我的建议是对每个表单数据使用“唯一”参数键。

代码语言:javascript
复制
curl --location --request POST 'http://localhost:8080/' --form 'medias[item]=@file1.jpeg' --form 'medias[item1]=@file2.jpeg'

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70826326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档