Dynamic Web Development with Seaside

10.7File Uploads

You can use a form to allow a user to upload a file. Here is how you would construct a simple form for a file upload.

UploadForm>>renderContentOn: html
html form multipart; with: [
html fileUpload
callback: [ :value | self receiveFile: value ].
html submitButton: 'Send File' ]

This code will produce a form, as shown in Figure 81. Some browsers may also display a text input field so you can enter the file path.

File uploads

You must send the multipart message to the form brush if you want to use the form for file uploads (as shown in this example). If you forget to do this, the upload won’t work.

Press the Choose File button to select the file, then press Send File to start the upload. When the upload completes, Seaside will invoke our callback which sends the receiveFile: message with a WAFile object that represents your file. As an example, the method below will save the file in a directory called uploads in Pharo.

UploadForm>>receiveFile: aFile
| stream |
stream := (FileDirectory default directoryNamed: 'uploads')
forceNewFileNamed: aFile fileName.
[ stream binary; nextPutAll: aFile rawContents ]
ensure: [ stream close ]

Note that it is possible to press the Send File button before selecting a file. In this case the callback is not triggered.

To make this method more robust, you could also check for empty files and devise a check that would prevent malicious persons from uploading many large files in an attempt to fill up your disk space. Note also that this method will quietly replace an existing file with the same name. You could easily change this method so that it checks for duplicate file names or tests the size of the file before saving it.

Alternatively you can offer to download the file again. Add an instance variable called file and change your code according to the following example:

UploadForm>>renderContentOn: html
html form multipart; with: [
html fileUpload
callback: [ :value | file := value ].
html submitButton: 'Send File' ].
file notNil ifTrue: [
html anchor
callback: [ self downloadFile ];
with: 'Download' ]
self requestContext respond: [ :response |
contentType: file contentType;
document: file rawContents asString;
attachmentWithFileName: file fileName ]

Copyright © 22 April 2024 Stéphane Ducasse, Lukas Renggli, C. David Shaffer, Rick Zaccone
This book is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 license.

This book is published using Seaside, Magritte and the Pier book publishing engine.