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/