#scala #playframework #play-ws
#scala #playframework #воспроизведение-ws
Вопрос:
Я реализую внешний API, в котором мне нужно отправить вложение файла в комплекте с мета-частью JSON.
Следующий код не принимается сервером, поскольку Play жестко кодирует тип содержимого DataPart
to text/plain
, и сервер ожидает application/json
val meta = Json.obj(
"name" -> s"Invoice ${invoiceNumber}.pdf",
"referenceType" -> "INVOICE",
"referenceId" -> 42
)
ws.url("{API-URL}")
.addHttpHeaders("Authorization" -> s"Bearer ${accessToken}")
.post(Source(DataPart("meta", meta.toString) :: FilePart("file", s"Invoice ${invoiceNumber}.pdf", Option("application/pdf"), FileIO.fromPath(file.toPath)) :: List()))
.map(res => {
logger.debug("Status: " res.status)
logger.debug("JSON: " res.json)
Right(invoiceNumber)
})
Примером команды curl (которую я протестировал и проверил) для конечной точки API является:
curl -H "Authorization: Bearer {accessToken}"
-F 'meta={"name": "Invoive 4.pdf", "referenceType": "INVOICE", "referenceId": 42 }
;type=application/json'
-F "file=@Invoice.pdf"
'{API-URL}'
Есть ли простой способ либо заставить DataPart
использовать другой тип содержимого, либо использовать другую часть, чтобы получить больше контроля над тем, что я отправляю?
Ответ №1:
Я нашел решение проблемы:
Сначала я создаю временный файл для хранения метаданных
val meta = new File(s"/tmp/${UUID.randomUUID()}")
Files.write(meta.toPath, Json.obj(
"name" -> s"Invoice ${invoiceNumber}.pdf",
"referenceType" -> "INVOICE",
"referenceId" -> 42
).toString.getBytes)
Затем я использую два FilePart
в своем запросе:
ws.url("{API-URL}")
.addHttpHeaders("Authorization" -> s"Bearer ${accessToken}")
.post(Source(FilePart("meta", "", Option("application/json"), FileIO.fromPath(meta.toPath)) :: FilePart("file", s"Invoice ${invoiceNumber}.pdf", Option("application/pdf"), FileIO.fromPath(file.toPath)) :: List()))
.map(res => {
logger.debug("Status: " res.status)
logger.debug("JSON: " res.json)
Right(invoiceNumber)
})