File Uploads
A special case of using form data is handling file uploads.
There are two main form encoding types:
- application/x-www-form-urlencoded (the default)
- multipart/form-data
When you wish to include file upload elements, you must choose multipart/form-data as your form's enctype
(encoding) type.
All code used below can be seen in action as a complete example at https://github.com/iamjono/perfect-file-uploads.
An example HTML form containing the correct encoding and file input element might be represented like this:
<form
method="POST"
enctype="multipart/form-data"
action="/upload">
<input type="file" name="filetoupload">
<br>
<input type="submit">
</form>
Receiving the File on the Server Side
Because the form is a POST method, we will handle the route with a method: .post
:
var routes = Routes() routes.add( method: .post, uri: "/upload", handler: handler) server.addRoutes(routes)
Once the request has been offloaded to the handler
we can:
// Grab the fileUploads array and see what's there // If this POST was not multi-part, then this array will be empty if let uploads = request.postFileUploads, uploads.count > 0 { // Create an array of dictionaries which will show what was uploaded var ary = [[String:Any]]() for upload in uploads { ary.append([ "fieldName": upload.fieldName, "contentType": upload.contentType, "fileName": upload.fileName, "fileSize": upload.fileSize, "tmpFileName": upload.tmpFileName ]) } values["files"] = ary values["count"] = ary.count }
As demonstrated above, the file(s) uploaded are represented by the request.postFileUploads
array, and the various properties such as fileName
, fileSize
and tmpFileName
can be accessed from each array component.
Note: The files uploaded are placed in a temporary directory. It is your responsibility to move them into the desired location.
So let's create a directory to hold the uploaded files. This directory is outside of the webroot directory for security reasons:
// create uploads dir to store files let fileDir = Dir(Dir.workingDir.path + "files") do { try fileDir.create() } catch { print(error) }
Next, inside the for upload in uploads
code block, we will create the action for the file to be moved:
// move file let thisFile = File(upload.tmpFileName) do { let _ = try thisFile.moveTo(path: fileDir.path + upload.fileName, overWrite: true) } catch { print(error) }
Now the uploaded files will move to the specified directory with the original filename restored.
For more information on file system manipulation, see the Directory Operations and File Operations chapters.