Skip to content

Commit 3fac025

Browse files
author
May
authored
Merge pull request #18 from MayMeow/dev/version-2-patch3
Removedrestricted characters from filenames before uploading
2 parents 6992a4d + 58d993d commit 3fac025

File tree

6 files changed

+99
-118
lines changed

6 files changed

+99
-118
lines changed

README.md

Lines changed: 59 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
# 🆙 FileUpload plugin for CakePHP
22

3-
Cakephp plugin to upload files to storage and download them. Currently are supported:
3+
:warning: This is readme for version 2.x. For 1.x go to [v1.1.2](https://github.com/MayMeow/cakephp-fileupload/tree/v1.1.2) release.
44

5-
- Local storage
6-
- S3 Compatible storage
5+
### :stop_sign: Breaking changes (read before use)
6+
7+
Version 2.x is not compatibile with cakephp lower than 5.x and it is not backward compatibile with previous releases of this plugins.
8+
9+
- S3 storage support was removed (will be added in future relases)
10+
- Bunny CND storage support was added
11+
- All components and Managers was rewritten.
712

813
And supported actions are upload and download.
914

@@ -16,152 +21,92 @@ The recommended way to install composer packages is:
1621
## 🐘 From packagist
1722

1823
```
19-
composer require maymeow/file-upload
24+
composer require maymeow/file-upload "^2.0.0"
2025
```
2126

2227
## Usage
2328

24-
To load plugin addd to `Application.php`
29+
Add configuration somewhere to your config files
2530

2631
```php
27-
$this->addPlugin('FileUpload');
32+
'Storage' => [
33+
'defaultStorageType' => env('STORAGE_DEFAULT_STORAGE_TYPE', 'local'),
34+
'local' => [
35+
'managerClass' => LocalStorageManager::class,
36+
'storagePath' => env('STORAGE_LOCAL_STORAGE_PATH', ROOT . DS . 'storage' . DS),
37+
],
38+
'bunny' => [
39+
'managerClass' => BunnyStorageManager::class,
40+
'cdnDomain' => env('BUNNY_STORAGE_CDN_DOMAIN', ''), // your cnd url
41+
'region' => env('BUNNY_STORAGE_REGION', ''), // region, empty is DE
42+
'baseHostName' => 'storage.bunnycdn.com', // base host name not changeable
43+
'storageZone' => env('BUNNY_STORAGE_ZONE', ''), // your storage zone name
44+
'storageZonePath' => env('BUNNY_STORAGE_ZONE_PATH', ''), // folder in zono
45+
'accessKey' => env('BUNNY_STORAGE_ACCESS_KEY', ''), // API key for write access
46+
]
47+
]
2848
```
2949

30-
Next load it in controllers where you want to use it. To use default config
50+
For bunny cdn minimal configuration is to have folowing keys configured
3151

32-
```php
33-
public function initialize(): void
34-
{
35-
parent::initialize();
36-
$this->loadComponent('FileUpload.Upload');
37-
$this->loadComponent('FileUpload.Dowmload'); // in case you wan to download files
38-
}
52+
```ini
53+
BUNNY_STORAGE_ACCESS_KEY=
54+
BUNNY_STORAGE_CDN_DOMAIN=
55+
BUNNY_STORAGE_ZONE=
3956
```
4057

41-
## Using local storage
58+
If you need/want nginx to server your static files without PHP set `STORAGE_LOCAL_STORAGE_PATH` location to whe webroot folder.
4259

43-
Commands above are loaded with default configuration:
44-
- Using Local filesystem: type is set to `local`
45-
- Data are stored in `sotrage` folder in root of your application - This folder is not public and cannot be served directly from webserver. You need to use `DownloadComponent` to get files
46-
- Field name for uploading files is `uploaded_file`
47-
- Allowed are all file types
60+
Load plugin with adding
4861

4962
```php
50-
public function initialize(): void
51-
{
52-
parent::initialize();
53-
$this->loadComponent('FileUpload.Upload', [
54-
'fieldName' => 'your_form_file_field',
55-
'storagePath' => 'path_to_storage',
56-
'allowedFileTypes' => '*'
57-
]);
58-
}
63+
$this->addPlugin('FileUpload'); // in your Application.php bootstrap function
5964
```
6065

61-
For `allowedFileTypes` use `'allowedFileTypes' => '*'` for all file types or `'allowedFileTypes' => ['type1', 'type2']` for your expected file types. If file have not allowed type Component will throw `Cake\Http\Exception\HttpException`.
62-
63-
Using local storage (default option) you can use default config but do not forge to change allowed file types and form field nam from which you uploading file to server.
64-
65-
## Using S3 storage
66-
67-
For S3 storage configuration is pretty same as configuration above, but you have to change type to `s3` instead of `local` which is default as follows
66+
or you can add your plugin with `plugins.php` config file
6867

6968
```php
70-
public function initialize(): void
71-
{
72-
parent::initialize();
73-
$this->loadComponent('FileUpload.Upload', [
74-
'fieldName' => 'your_form_file_field',
75-
'storagePath' => 'bucket_name',
76-
'storage_type' => 's3'
77-
]);
78-
}
69+
return [
70+
// .. your other plugins
71+
'FileUpload' => [],
72+
];
7973
```
8074

81-
:exclamation: Dont forget to change configuration for `DownloadComponent` too if you planing using it.
82-
83-
Next add configuration for s3 server to your config file `app_local.php` for example as follows:
75+
Loading components
8476

8577
```php
86-
'S3' => [
87-
'version' => 'latest',
88-
'region' => 'us-east-1',
89-
'endpoint' => 'http://cake_minio:9000',
90-
'use_path_style_endpoint' => true,
91-
'credentials' => [
92-
'key' => 'minioadmin',
93-
'secret' => 'minioadmin',
94-
],
95-
]
96-
```
78+
$config = Configure::read('Storage.local'); // or Storage.bunny
9779

98-
Config above is for using minio with my [CakePHP starte kit](https://github.com/MayMeow/cakephp-starter-kit). Change it for your needs.
80+
// or by setting it with .env STORAGE_DEFAULT_STORAGE_TYPE
81+
$storageType = Configure::read('Storage.defaultStorageType');
82+
$config = Configure::read('Storage.' . $storageType);
9983

84+
$this->loadComponent('FileUpload.Upload', $config);
85+
$this->loadComponent('FileUpload.Download', $config);
86+
```
10087

101-
## Uploading files
102-
88+
Uploading files
10389

10490
```php
105-
/**
106-
* @throws \HttpException
107-
* @return \Cake\Http\Response|null|void
108-
*/
109-
public function upload()
110-
{
111-
$uploadForm = new UploadForm();
112-
113-
if ($this->request->is('post')) {
114-
$uploadedFile = $this->Upload->getFile($this->request);
115-
116-
// Create new Entity and store info about uploaded file
117-
$file = $this->Files->newEmptyEntity();
118-
119-
$file->name = $uploadedFile->getFileName();
120-
$file->path = $uploadedFile->getPath();
121-
122-
$this->Files->save($file);
91+
$file = $this->Upload->getFile($this);
92+
// do something with file
12393

124-
return $this->redirect($this->referer());
125-
}
126-
127-
$this->set(compact('uploadForm'));
128-
}
94+
// store your file name in database
95+
$file->getFileName(); // sanitized file name - with removed restricted characters in the name
12996
```
13097

131-
## Downloading files
132-
133-
13498
```php
135-
/**
136-
* @param string $fileName
137-
* @return \Cake\Http\Response|void
138-
*/
139-
public function download($fileName)
140-
{
141-
$downloadedFile = $this->Download->getFile($fileName);
142-
143-
$response = $this->response;
144-
$response = $response->withStringBody($downloadedFile->getFileContent());
145-
$response = $response->withType($downloadedFile->getFileType());
146-
147-
if ($this->request->getParam('?.download') == true) {
148-
$response = $response->withDownload($fileName);
149-
}
150-
151-
return $response;
152-
}
99+
$file = $this->Download->getFile($resource->name);
100+
// do something with file
153101
```
154102

155-
## 🎯 Direction
103+
:memo: Note that the function above will read content of file and you then need to use response to push it to the viewer. If you want to do it without using PHP you will need to get URL of file and if you using local storage manager your folder need to be in webrootfolder.
156104

157-
* [x] Configurable field name
158-
* [x] Configurable path to storage
159-
* [x] Allowed file types
160-
* [x] Add S3 Support
161-
* [ ] Multiple file upload
162-
* [ ] File Size
105+
```php
106+
$file->get('storagePath'); // local: /patht/to/sorage or bunny: https://cdn.your.tld/path/to/folder/
107+
// combine it with filename from your database go download it
108+
```
163109

164-
💡 If you have more ideas then you can post issue on porect's GitHub page.
165110

166111
## License
167112

src/Controller/Component/UploadComponent.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class UploadComponent extends Component
2525
];
2626

2727
/**
28-
* Allowed storage types
28+
* Allowed stoage types
2929
*
3030
* @var string[]
3131
*/

src/File/PathUtils.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace FileUpload\File;
5+
6+
use Cake\Utility\Text;
7+
8+
class PathUtils
9+
{
10+
public static function fileNameSanitize(string $filename): string
11+
{
12+
// get extension even if filename has multiple dots
13+
$ext = pathinfo($filename, PATHINFO_EXTENSION);
14+
$filename = pathinfo($filename, PATHINFO_FILENAME);
15+
$filename = Text::slug($filename);
16+
17+
return $filename . '.' . $ext;
18+
}
19+
}

src/File/UploadedFileDecorator.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,13 @@ public function get(string $key): string
2828
{
2929
return $this->options[$key] ?? "";
3030
}
31+
32+
public function getFileName(): string
33+
{
34+
if (isset($this->options['fileName'])) {
35+
return $this->options['fileName'];
36+
}
37+
38+
return $this->originalData->getClientFilename();
39+
}
3140
}

src/Storage/BunnyStorageManager.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace FileUpload\Storage;
55

6+
use FileUpload\File\PathUtils;
67
use FileUpload\File\StoredFile;
78
use FileUpload\File\StoredFileInterface;
89
use FileUpload\File\UploadedFileDecorator;
@@ -22,7 +23,10 @@ public function put(UploadedFileInterface $fileObject): UploadedFileDecorator
2223
{
2324
$accessKey = $this->getConfig('accessKey');
2425
$hostname = (!empty($this->getConfig('region'))) ? $this->getConfig('region') . '.' . $this->getConfig('baseHostName') : $this->getConfig('baseHostName');
25-
$url = $this->composeUrl($hostname, $this->getConfig('storageZone'), $this->getConfig('storageZonePath'), $fileObject->getClientFilename());
26+
27+
$fileName = PathUtils::fileNameSanitize($fileObject->getClientFilename());
28+
29+
$url = $this->composeUrl($hostname, $this->getConfig('storageZone'), $this->getConfig('storageZonePath'), $fileName);
2630

2731
$ch = curl_init();
2832

@@ -49,7 +53,8 @@ public function put(UploadedFileInterface $fileObject): UploadedFileDecorator
4953
}
5054

5155
$file = new UploadedFileDecorator($fileObject, self::STORAGE_TYPE, [
52-
'storagePath' => $this->composeUrl($this->getConfig('cdnDomain'))
56+
'storagePath' => $this->composeUrl($this->getConfig('cdnDomain'), $this->getConfig('storageZonePath')),
57+
'fileName' => $fileName,
5358
]);
5459

5560
return $file;

src/Storage/LocalStorageManager.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace FileUpload\Storage;
55

6+
use FileUpload\File\PathUtils;
67
use FileUpload\File\StoredFile;
78
use FileUpload\File\StoredFileInterface;
89
use FileUpload\File\UploadedFileDecorator;
@@ -19,10 +20,12 @@ class LocalStorageManager extends StorageManager
1920
*/
2021
public function put(UploadedFileInterface $fileObject): UploadedFileDecorator
2122
{
22-
$fileObject->moveTo($this->getConfig('storagePath') . $fileObject->getClientFilename());
23+
$fileName = PathUtils::fileNameSanitize($fileObject->getClientFilename());
24+
$fileObject->moveTo($this->getConfig('storagePath') . $fileName);
2325

2426
$uploadedFile = new UploadedFileDecorator($fileObject, self::STORAGE_TYPE, options: [
2527
'storagePath' => $this->getConfig('storagePath'),
28+
'fileName' => $fileName,
2629
]);
2730

2831
return $uploadedFile;

0 commit comments

Comments
 (0)