docs
reference
tessl install tessl/maven-io-quarkus--quarkus-rest@3.15.0A Jakarta REST implementation utilizing build time processing and Vert.x for high-performance REST endpoints with reactive programming support, security integration, and cloud-native features.
Quarkus REST provides built-in support for handling file uploads with automatic temporary file management, configurable upload directories, and support for both java.io.File and java.nio.file.Path types.
Handle file uploads using @FormParam with File or Path types:
import java.io.File;
import java.nio.file.Path;
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@FormParam("file") File file) {
// Process the uploaded file
long size = file.length();
String name = file.getName();
// File is automatically cleaned up after request completes
return Response.ok("Uploaded: " + name + " (" + size + " bytes)").build();
}Path is recommended for modern file handling:
@POST
@Path("/upload-path")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFilePath(@FormParam("file") Path file) {
try {
long size = Files.size(file);
String name = file.getFileName().toString();
return Response.ok("Uploaded: " + name + " (" + size + " bytes)").build();
} catch (IOException e) {
return Response.serverError().build();
}
}Handle multiple form fields including files:
@POST
@Path("/upload-with-metadata")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadWithMetadata(
@FormParam("file") File file,
@FormParam("description") String description,
@FormParam("category") String category
) {
// Process file with additional metadata
return Response.ok()
.entity("File: " + file.getName() + ", Description: " + description)
.build();
}Handle multiple files in a single request:
@POST
@Path("/upload-multiple")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadMultipleFiles(
@FormParam("files") List<File> files
) {
List<String> filenames = files.stream()
.map(File::getName)
.collect(Collectors.toList());
return Response.ok("Uploaded " + files.size() + " files: " + filenames).build();
}Handle file uploads reactively:
@POST
@Path("/upload-async")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Uni<Response> uploadFileAsync(@FormParam("file") File file) {
return Uni.createFrom().item(() -> {
// Process file asynchronously
long size = file.length();
return Response.ok("Uploaded: " + size + " bytes").build();
});
}Configure multipart form handling via quarkus.rest.multipart.* properties:
# Default charset for multipart input parts
quarkus.rest.multipart.input-part.default-charset=UTF-8
# Maximum file upload size (Quarkus HTTP config)
quarkus.http.limits.max-body-size=10Mpackage io.quarkus.resteasy.reactive.server.runtime;
interface ResteasyReactiveServerRuntimeConfig {
MultipartConfigGroup multipart();
interface MultipartConfigGroup {
InputPartConfigGroup inputPart();
interface InputPartConfigGroup {
Charset defaultCharset(); // Default: UTF-8
}
}
}Uploaded files are stored as temporary files and automatically deleted after the request completes:
@POST
@Path("/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(@FormParam("file") Path uploadedFile) {
// uploadedFile is a temporary file
// It will be automatically deleted when the request completes
// If you need to keep the file, copy it to a permanent location
Path permanent = Paths.get("/permanent/storage", uploadedFile.getFileName().toString());
Files.copy(uploadedFile, permanent);
return Response.ok().build();
}Configure the upload directory for temporary files:
package io.quarkus.resteasy.reactive.server.runtime;
class QuarkusServerPathBodyHandler implements ServerMessageBodyReader<Path> {
/**
* Creates a temporary file in the configured upload directory
* with an optional completion callback for cleanup
*/
static Path createFile(ServerRequestContext context);
}Control maximum upload sizes via HTTP configuration:
# Maximum request body size (applies to all requests including file uploads)
quarkus.http.limits.max-body-size=100M
# Disable body size limit (not recommended for production)
quarkus.http.limits.max-body-size=-1For very large files, consider streaming to avoid memory issues:
@POST
@Path("/upload-stream")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadLargeFile(@FormParam("file") Path file) {
try (InputStream input = Files.newInputStream(file);
OutputStream output = Files.newOutputStream(Paths.get("/storage/large-file"))) {
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
return Response.ok("Large file uploaded successfully").build();
} catch (IOException e) {
return Response.serverError().build();
}
}Access file metadata from multipart uploads:
import org.jboss.resteasy.reactive.multipart.FileUpload;
@POST
@Path("/upload-info")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadWithInfo(@RestForm FileUpload file) {
String filename = file.fileName();
String contentType = file.contentType();
long size = file.size();
Path filePath = file.filePath();
return Response.ok()
.entity("File: " + filename + ", Type: " + contentType + ", Size: " + size)
.build();
}Quarkus REST uses ServerMessageBodyReader implementations for file handling:
package io.quarkus.resteasy.reactive.server.runtime;
class QuarkusServerFileBodyHandler implements ServerMessageBodyReader<File> {
boolean isReadable(Class<?> type, Type genericType,
ResteasyReactiveResourceInfo lazyMethod, MediaType mediaType);
File readFrom(Class<File> type, Type genericType,
MediaType mediaType, ServerRequestContext context);
}package io.quarkus.resteasy.reactive.server.runtime;
class QuarkusServerPathBodyHandler implements ServerMessageBodyReader<Path> {
boolean isReadable(Class<?> type, Type genericType,
ResteasyReactiveResourceInfo lazyMethod, MediaType mediaType);
Path readFrom(Class<Path> type, Type genericType,
MediaType mediaType, ServerRequestContext context);
static Path createFile(ServerRequestContext context);
}Handle upload errors appropriately:
@POST
@Path("/upload-safe")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadSafe(@FormParam("file") File file) {
if (file == null) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("No file provided")
.build();
}
if (file.length() == 0) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Empty file")
.build();
}
try {
// Process file
processFile(file);
return Response.ok("File uploaded successfully").build();
} catch (Exception e) {
return Response.serverError()
.entity("Failed to process file: " + e.getMessage())
.build();
}
}@POST
@Path("/upload-image")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadImage(@RestForm FileUpload file) {
String contentType = file.contentType();
if (!contentType.startsWith("image/")) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Only image files allowed")
.build();
}
// Process image
return Response.ok().build();
}Limit File Sizes: Always configure maximum upload sizes
Scan for Malware: Consider virus scanning for user-uploaded files
Sanitize Filenames: Clean filenames before storing
private String sanitizeFilename(String filename) {
return filename.replaceAll("[^a-zA-Z0-9.-]", "_");
}Use Path over File: Path is more modern and flexible
Handle Cleanup: Files are auto-cleaned, but copy to permanent storage if needed
Validate Early: Check file size, type, and content before processing
Use Streaming: For large files, stream instead of loading into memory
Configure Limits: Always set max-body-size in production
Temporary Storage: Be aware of disk space for temporary file storage
Error Messages: Provide clear error messages for validation failures