Ninja offers direct access to file uploads in your controller method. This
is accomplished via the Context object and two of its methods:
context.isMultipart() to check if we are dealing with a multipart upload
and context.getFileItemIterator() to iterate through potential
files.
Usually you render a form that links to the controller that will handle the
upload. In the following case we are using a route to /upload.
<form method="post" enctype="multipart/form-data" action="/upload">
Please specify file to upload: <input type="file" name="upfile"><br />
<input type="submit" value="submit">
</form>
Note that you'll be able to still get your other form values inside a proper DTO :
public Result upload(Context context, MyDto formObject, @Param(“file”) File file) { … }.
The controller at /uploadFinish will then handle the upload:
public Result uploadFinish(Context context) throws Exception {
// Make sure the context really is a multipart context...
if (context.isMultipart()) {
// This is the iterator we can use to iterate over the
// contents of the request.
FileItemIterator fileItemIterator = context
.getFileItemIterator();
while (fileItemIterator.hasNext()) {
FileItemStream item = fileItemIterator.next();
String name = item.getFieldName();
InputStream stream = item.openStream();
String contentType = item.getContentType();
if (item.isFormField()) {
// do something with the form field
} else {
// process file as input stream
}
}
}
// We always return ok. You don't want to do that in production ;)
return Results.ok();
}
The controller at /uploadFinish can automatically handle the upload, and return either a FileItem, InputStream or File.
Using FileItem allows provides access to additional properties, like getFileName() to get the original file name sent by the browser. NOTE: By default, the file provider is set to NoFileItemProvider - in order to use this new way, you need to configure a file provider as described below.
public Result uploadFinish(Context context, @Param("upfile") FileItem upfile) throws Exception {
}
or
public Result uploadFinish(Context context, @Param("upfile") InputStream upfile) throws Exception {
}
or
public Result uploadFinish(Context context, @Param("upfile") File upfile) throws Exception {
}
or
public Result uploadFinish(Context context) throws Exception {
FileItem upfile = context.getParameterAsFileItem("upfile");
}
Ninja comes with two providers to choose between in-memory and disk file for storing uploaded content:
MemoryFileItemProvider, to stores the file bytes into memoryDiskFileItemProvider, to stores the file content to disk in a temporary folder, that can be set using the uploads.temp_folder ninja propertyIn all case, you can limit the size of each file using uploads.max_file_size and the total size of all files using uploads.max_total_size ninja properties.
Ninja let's you configure the file provider to use at different places:
By default, the provider is set to NoFileItemProvider, who simply reverts to the manual way of handling file.
To define a provider in a module, simply use a bind:
bind(FileItemProvider.class).to(MemoryFileItemProvider.class)
To define a provider in a controller class and/or method, use an annotation:
@FileProvider(DiskFileItemProvider.class)
@Singleton
public class MyController {
@FileProvider(MemoryFileItemProvider.class)
public Result myRouteMethod() {
// This will use the MemoryFileItemProvider defined at method level
}
public Result myOtherRouteMethod() {
// This will use the DiskFileItemProvider defined at class level
}
}
Ninja uses Apache Commons-upload to implement the upload functionality. Therefore you can also refer to their excellent manual for more information at: http://commons.apache.org/proper/commons-fileupload/