3.4. Working With Files
For security puposes, the system purposely discourages using
move_uploaded_file()
.
It’s recommended if you want to upload a file to the server to first encode
the file to base64 and reassign the key to
that base64 value.
INFORMATION: Though you could use move_uploaded_file() in your custom controllers.
3.4.1. Upload to Server
To upload a file you should create a form and set the method to post
like the
following example.
Figure 3.4.1.A. Basic Form Post
<form method="post">
...
</form>
In Cradle, the following snippet, when wrapped around the form above, can be used to perform this base64 process.
Figure 3.4.1.B. Doon File Field
<table class="table table-striped file-field" data-do="file-field" data-name="custom_file">
<thead>
<tr>
<th>Preview</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr class="file-field-none">
<td colspan="5">
<div class="alert alert-info">No File Selected</div>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5">
<button class="file-field-upload btn btn-info" type="button">
Choose File
</button>
</td>
</tr>
</tfoot>
</table>
The above HTML uses a Doon interface to perform its front end logic. To learn more about these interfaces visit 4.5. Intro to Doon & Acquire.
When the form is submitted in this manner, custom_file
as in
$_POST['custom_file']
will have the base64 version of the file. From here,
you can process that file using PHP’s base64_decode()
using the following logic.
Figure 3.4.1.C. Processing a BASE64 in PHP
$path = __DIR__ . '/upload/custom_file.png';
$base64 = substr($_POST['custom_file'], strpos($_POST['custom_file'], ',') + 1);
file_put_contents($path, base64_decode($base64));
Cradle has a set of functions that help working with base64 files easier and can be used like the following examples.
Figure 3.4.1.D. System File Class Handler
use Cradle\Module\Utility\File;
...
$data = $_POST['custom_file'];
$path = __DIR__ . '/upload';
//returns the mime type from base64 file data
$mime = File::getMimeFromData($data); //--> image/png
//returns the extension from base64 file data
$extension = File::getExtensionFromData($data); //--> png
//saves a bsae64 into a file and returns the file path
$link = File::base64ToUpload($data, $path);
//returns the mime type from a file path
$mime = File::getMimeFromLink($link); //--> image/png
//returns the extension from a file path
$extension = File::getExtensionFromLink($link); //--> png
INFORMATION: To remain unopinionated, the File class is found in `/module/utility`
in case you need to add or change the way it works.
3.4.2. Upload to CDN
The system also provides an easy way to interact with a CDN,
AWS S3 particularly in this case. You first need
to make sure you have S3 credentials before continuing. Then enter the
credentials in services.php
Figure 3.4.2.A. config/services.php
...
's3-main' => [
'region' => '<AWS REGION>',
'token' => '<AWS TOKEN>',
'secret' => '<AWS SECRET>',
'bucket' => '<S3 BUCKET>',
'host' => 'https://<AWS REGION>.amazonaws.com',
'root' => '<ROOT PATH IN BUCKET OR REMOVE THIS>'
]
...
The following describes what each configure is and how to use it.
region
- this is the s3 region for exampleap-southeast-1
token
- this is the IAM token that is connected with S3secret
- this is the IAM token secret that is connected with S3bucket
- this is the name of the bucket you created on S3host
- this is the accessible public host of the S3 for examplehttps://s3-ap-southeast-1.amazonaws.com
root
- if your files need to be uploaded to a particular folder in the bucket for example/sub/folder
3.4.2.1. Client Side Uploading to CDN
To prevent the application server from accepting uploads and processing files directly, it is recommended to forward that load from the client (browser) side directly to the CDN. This Client Side Uploading process remains to be secure since CDN by nature do not process server side code.
While the actual documentation to get this done is highly advance, fortunately Cradle has wrappers to make this process easier. In a route, you simply need to add the following lines of code.
Figure 3.4.2.1.A. controller.php
use Cradle\Module\Utility\File;
...
//add CDN
$config = $this->package('global')->service('s3-main');
$data['cdn_config'] = File::getS3Client($config);
Then take $data
and pass it on to your template to process. The template
(if in Handlebars) would look like the following.
Figure 3.4.2.1.B. template.html
<form
class="box"
method="post"
data-do="cdn-upload"
data-on="submit"
data-progress="We are uploading your files. Please do not refresh page."
data-complete="Upload Complete"
data-enctype="{{cdn_config.form.enctype}}"
data-method="{{cdn_config.form.method}}"
data-action="{{cdn_config.form.action}}"
data-cdn="{{cdn_config.form.action}}"
data-acl="{{cdn_config.inputs.acl}}"
data-key="{{cdn_config.inputs.key}}"
data-credential="{{cdn_config.inputs.X-Amz-Credential}}"
data-algorythm="{{cdn_config.inputs.X-Amz-Algorithm}}"
data-date="{{cdn_config.inputs.X-Amz-Date}}"
data-policy="{{cdn_config.inputs.Policy}}"
data-signature="{{cdn_config.inputs.X-Amz-Signature}}"
>
...
</form>
The above HTML again uses a Doon interface to perform its front end logic and you don’t really need to worry about what data is actually passed to these.
3.4.3. Deploying assets to CDN
Additionally the system can upload your static assets like images, JavaScript, fonts, CSS, etc. to the CDN “automagically”. The following commands can do just that.
Figure 3.4.3.A. Uploading assets to CDN
$ bin/cradle deploy s3
$ bin/cradle deploy s3 --include-yarn
$ bin/cradle deploy s3 --include-upload
$ bin/cradle deploy s3 --include-yarn --include-upload
--include-yarn
- This is to determine if we should also deploy thenode_modules
folder. Since that folder is usually big, it could be literally costly to upload it every time. Usually you would want to add this flag if this is the first time uploading to the bucket.--include-upload
- This is to determine if we should also upload the/public/upload
folder which is usually has placeholder files if you are in a development environment you may not want to upload that all the time.
These commands base where to upload on your s3-main
configurations in
config/services.php
and upload assets only found in the /public
folder. To
make sure the assets are pointed to the right place we need to add an extra
configuration to settings.php
which looks like the following code.
Figure 3.4.3.B. config/settings.php
...
'cdn' => 'https://<AWS REGION>.amazonaws.com'
...