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 memory - DiskFileItemProvider, to stores the file content to disk in a temporary folder, that can be set using the uploads.temp_folder ninja property
In 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: - in a module, using a bind to configure a default provider - in a controller class, to override the default’s provider configured in the module - in a controller method, to override the class or module provider
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/