我正在尝试更新旧的 Java 软件并使用 RESTEASY / Reactive / Microprofile 将其移植到 Quarkus,这会在 Trello 上向卡片添加图像(Trello 文档:Create attachment at card。请注意:该文档有一些缺乏并且不能被视为完全“真实”)。为此,我必须发送具有某些属性(名称、文件名、mimeType、setCover 和二进制文件)的多部分/表单数据。要点:将文件作为二进制文件发送。
我的旧软件运行正常:
String name = "Cover.jpg";
File tempImage = new File(name);
try {
Client client = ClientBuilder.newClient(new ClientConfig())
.register(MultiPartFeature.class);
String mime = "image/jpg";
byte[] buffer = Files.readAllBytes(Paths.get("/PATH/" + name));
// Save temporary
FileOutputStream fos = new FileOutputStream(tempImage);
fos.write(buffer);
fos.flush();
fos.close();
FileDataBodyPart filePart = new FileDataBodyPart("file", tempImage);
FormDataMultiPart formDataMultiPart = new FormDataMultiPart();
final FormDataMultiPart multipart = (FormDataMultiPart) formDataMultiPart
.field("mimeType", mime)
.field("setCover", "true").field("name", name).bodyPart(filePart);
// Add Cover
WebTarget coverService = client.target(URI.create("https://api.trello.com/1/cards/CARD_ID/attachments"));
String coverResponse = coverService.queryParam("key", "KEY").queryParam("token", "TOKEN").request()
.header("Accept", "application/json")
.post(Entity.entity(multipart, multipart.getMediaType()), String.class);
产生类似的东西:
1 * Sending client request on thread main
1 > POST https://api.trello.com/1/cards/CARD_ID/attachments?key=KEY&token=TOKEN
1 > Accept: application/json
1 > Content-Type: multipart/form-data
--Boundary_1_2089589253_1678121120116
Content-Type: text/plain
Content-Disposition: form-data; name="mimeType"
image/jpg
--Boundary_1_2089589253_1678121120116
Content-Type: text/plain
Content-Disposition: form-data; name="setCover"
true
--Boundary_1_2089589253_1678121120116
Content-Type: text/plain
Content-Disposition: form-data; name="name"
Cover.jpg
--Boundary_1_2089589253_1678121120116
Content-Type: image/jpeg
Content-Disposition: form-data; filename="Cover.jpg"; modification-date="Mon, 06 Mar 2023 16:45:19 GMT"; size=105034; name="file"
<BINARY! content>
--Boundary_1_2089589253_1678121120116--
我尝试了很多东西,包括 quarkus.io 上的 multipart 文档。文档的要点:
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
String sendMultipartData(@MultipartForm MultipartBody data);
此外,我几乎尝试了在互联网上找到的所有内容,但没有任何效果。问题是大多数时候:文件的内容不是以二进制形式发送,而是以 Base64 形式发送。
那么我如何发送带有二进制内容的 multipart 与“旧”方式完全一样,但使用 Quarkus?我已经尝试了几个星期了,真的很沮丧。
这是我最后试过的代码:
@Path(ADD_ATTACHMENT_CARD_URL)
@POST
@javax.ws.rs.Consumes(MediaType.MULTIPART_FORM_DATA)
@Consumes(MediaType.MULTIPART_FORM_DATA)
@ClientHeaderParam(name = "Accept", value = MediaType.APPLICATION_JSON)
@ClientHeaderParam(name = "User-Agent", value = "FawnKeeper")
public void setCover(@QueryParam("key") String key, @QueryParam("token") String token, @PathParam("id") String id,@MultipartForm MultipartBody file);
MultipartBody 是这样的(改变了很多,第一次尝试像 Quarkus 文档一样使用 InputStream,但结果是“没有找到要转换为字符串的转换器......”):
请注意:我首先尝试在每个成员上使用注解@FormParam,但没有成功(“Converter...”)。
public class MultipartBody implements Serializable {
@PartType(MediaType.TEXT_PLAIN)
public String mimeType = "image/jpg";
@PartType(MediaType.TEXT_PLAIN)
public String setCover = "false";
@PartType(MediaType.TEXT_PLAIN)
public String name = "Cover.jpg";
@PartType("image/jpeg")
public File file;
}
我也尝试过使用 vertx 客户端,但没有运气......
请注意:由于依赖关系冲突,我无法使用旧代码。
如果有人能给我指出正确的方向或者之前用 Trello 做过这件事,我真的很高兴。谢谢你的时间!
让它随机工作...
对于所有遇到类似问题的人,这就是我如何让它工作的。
创建 MultiDataFormOutput 实例,像这样填充它:
byte[] buffer = getBufferFromFile();
String filename = "MyFile.jpg";
MultipartFormDataOutput dataOutput = new MultipartFormDataOutput();
dataOutput.addFormData("mimeType", mimeType, MediaType.TEXT_PLAIN_TYPE);
dataOutput.addFormData("setCover", "true", MediaType.TEXT_PLAIN_TYPE);
dataOutput.addFormData("name", filename, MediaType.TEXT_PLAIN_TYPE);
dataOutput.addFormData("file", buffer, MediaType.APPLICATION_OCTET_STREAM_TYPE, filename);
在客户端界面我是这样做的:
// Just for clarification
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import org.jboss.resteasy.annotations.providers.multipart.PartType;
import jakarta.ws.rs.core.MediaType;
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataOutput;
@Path(ADD_ATTACHMENT_CARD_URL)
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@ClientHeaderParam(name = "Accept", value = MediaType.APPLICATION_JSON)
@ClientHeaderParam(name = "User-Agent", value = "FawnKeeper")
public void setCover(@QueryParam("key") String key, @QueryParam("token") String token, @PathParam("id") String id, @MultipartForm MultipartFormDataOutput file);
我之前尝试过几次,但没有用。主体始终仅包含“文件”的字符串表示形式 - MultipartFormDataOutput 对象。
为了使它与 Quarkus rest 客户端反应式一起工作,需要在 application.properties/yaml 中进行额外的配置:
quarkus.index-dependency.resteasy-multipart.group-id=org.jboss.resteasy
quarkus.index-dependency.resteasy-multipart.artifact-id=resteasy-multipart-provider
这是从经典休息客户端到反应式休息客户端让多部分工作的主要区别。
希望这对某人有帮助!