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



我正在创建一个gcloudhttp云函数,该函数必须接收一个">表单数据";用">媒体";字段,最多可以包含3个文件,这里是基本代码:

gcloud Java函数:

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());
});

}
}

我的简单请求:

curl --location --request POST 'http://localhost:8080/' 
--form 'medias=@"/file1.jpeg"' 
--form 'medias=@"/file2.jpeg"'

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

"java.lang.IollegalStateException:重复的密钥媒体(尝试合并值com.google.cloud.functions.invoker.http.HttpRequestImpl$HttpPartImpl@49e848cf

com.google.cloud.functions.invoker.http.HttpRequestImpl$HttpPartImpl@6d5d7015)">

相同的查询与";Springboot";通过将其指定为参数:

@RequestParam(value = "medias", required = false) MultipartFile[] medias

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

<dependency>
<groupId>com.google.cloud.functions</groupId>
<artifactId>functions-framework-api</artifactId>
<version>1.0.4</version>
<scope>provided</scope>
</dependency>

如本GCP文档中所述,您可以使用下面的示例代码处理具有多部分/表单数据内容类型的数据。

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()方法的源代码,发现它有自己的方法从表单数据中收集流,当每个数据只有一个键时,就会失败,如下所示:

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);
}
}

最后,我的建议是使用";独特的";每个表单数据的参数键。

curl --location --request POST 'http://localhost:8080/' --form 'medias[item]=@file1.jpeg' --form 'medias[item1]=@file2.jpeg'

最新更新