One constant thing in IT is that changes are getting quicker and quicker.
People who work in this business won't get bored. Definitely good place to be.
Recently I have been trying to implement the file upload functionality with Quarkus.
While the framework is building on a well established standards dated back to J2EE standard, the recent APIs are changing - and this happened quite often. The ecosystem has evolved through several REST implementations - RESTEasy Classic, RESTEasy Reactive, and now Quarkus REST (which is essentially RESTEasy Reactive rebranded).
What I have found was: the great post and video from Sebastian - explainging all the details, despite the update post are no longer the way Quarkus file upload works.
So let's revise the topic with some (again maybe in Quarkus wolrd not most shiny and recent - at the time you are reading this) but stable API: MultipartFormDataInput. It's actually the recommended approach when you need fine-grained control over multipart request parsing.
@Slf4j
@EndpointPath("/upload")
class UploadEndpoint {
@POST
Response upload(MultipartFormDataInput input) {
var metadata = metaDataIfNotFile(input.values)
var files = extractFiles(input.values, metadata)
files
.forEach { write(it) }
Response.status(201).entity(metadata).build()
}
def write(DataItem data) {
var uploads = Paths.get("./my-uploads")
var path = uploads.resolve(data.getFilename())
try {
if(!Files.exists(uploads)) {
Files.createDirectories(uploads)
}
Files.write(path, data.data)
} catch (e) {
e.printStackTrace()
}
}
static def metaDataIfNotFile(Map> formData) {
formData
.findAll { it.value.every { !it.fileItem } }
.collectEntries { k, formValues ->
[ (k): formValues.collect { it.value } ] }
}
def extractFiles(Map> values, metadata) {
values
.findAll { it.value.find { it.fileItem } }
.collectMany { extractData(it, metadata) }
}
def extractData(Map.Entry> entry, meta) {
entry.value
.findAll { it.fileItem && it.fileName?.trim() }
.collectMany { tryData(it, meta) }
}
def tryData(FormValue formValue, meta) {
try {
[
[
data : Files.readAllBytes(formValue.getFileItem().file),
filename: formValue.fileName,
metaData: meta
] as DataItem
]
} catch (e) {
e.printStackTrace()
[]
}
}
}
@ToString @EqualsAndHashCode
class DataItem {
byte[] data
String filename
Map> metaData
}
You can test it with curl:
curl -X POST http://localhost:8080/upload -F "file=@/path/to/file"
Files land in `./my-uploads/` directory.
The full working example can be found in my github.
| Quark - a kind of white cheese from Germany. Source: wikipedia, authored by Elskeletto |
No comments:
Post a Comment