Skip to content

Commit bf4e3ab

Browse files
committed
Merge pull request #1 from UniSharp/develop
Develop
2 parents f498288 + c535283 commit bf4e3ab

File tree

5 files changed

+335
-74
lines changed

5 files changed

+335
-74
lines changed

readme.md

Lines changed: 20 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@
44

55
Laravel File API is good way to handle files with Laravel Storage.
66

7-
### Install File API
7+
### Installation
88

9-
composer.json:
9+
1. Install File API
1010

11-
"require" : {
12-
"unisharp/laravel-fileapi" : "dev-master"
13-
},
14-
"repositories": {
15-
"type": "git",
16-
"url": "https://github.com/UniSharp/laravel-fileapi.git
17-
}
11+
```php
12+
composer require unisharp/laravel-fileapi
13+
```
1814

19-
save it and then
15+
1. Set service provider in `config/app.php`
2016

21-
composer update
17+
```php
18+
Unisharp\FileApi\FileApiServiceProvider::class,
19+
```
20+
21+
1. publish config file
22+
23+
```php
24+
php artisan vendor:publish --tag=fileapi_config
25+
```
26+
27+
1. fill the path in config/fileapi.php, it will generate routes for your files.
2228

2329
### Initialize File API
2430

@@ -31,44 +37,21 @@ or
3137
$fa = new FileApi('/images'); # initialize it by giving a base path
3238

3339

34-
### Save to Storage By Giving Lravel Upload File
40+
### Save to Storage By Giving Uploaded File
3541

36-
* Normal Usage
37-
38-
get unique filename
42+
* Default Usage : get unique filename
3943

4044
$file = $fa->save(\Input::file('image')); // => wfj412.jpg
4145

42-
or input files is an array
43-
44-
$files = [];
45-
foreach (\Input::file('images') as $file) {
46-
$files []= $fa->save('images');
47-
}
48-
4946
* Custimize your upload file name
5047

51-
$file = $fa->save('image', 'custimized_filename'); // => custimized_filename.jpg
48+
$file = $fa->save(\Input::file('image'), 'custimized_filename'); // => custimized_filename.jpg
5249

5350

5451
### Get file fullpath (abstract path from Laravel Storage)
5552

5653
$fa->getPath('wfj412.jpg'); // => '/images/wfj412.jpg'
5754

58-
### Routing your files
59-
60-
All uploaded files cannot found in public folder, because FileApi use Laravel Storage to store them.
61-
You can write a routing rules to get it. it will response file content and use http cache by default.
62-
63-
Route::get('/upload/{filename}', function ($filename) {
64-
$fa = new FileApi();
65-
return $fa->getResponse($filename);
66-
});
67-
68-
and it can add headers array by optional
69-
70-
return $fa->getResponse($filename, ['Content-Disposition', 'attachement']);
71-
7255
### Parse File Path to URL
7356
if you store your file into cloud storage and you want to get url cloud site,
7457
you can use url() method to get it

src/FileApi.php

Lines changed: 241 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
class FileApi
99
{
1010
protected $basepath;
11+
protected $default_sizes = ['S' => '96x96', 'M' => '256x256', 'L' => '480x480'];
12+
protected $thumb_sizes = null;
13+
protected $shouldCropThumb = false;
1114

1215
public function __construct($basepath = '/')
1316
{
@@ -22,49 +25,40 @@ public function __construct($basepath = '/')
2225
$this->basepath = $basepath;
2326
}
2427

25-
public function save(UploadedFile $upload_file, $cus_name = null)
28+
public function get($filename, $size = null)
2629
{
27-
$file = $this->moveFile($upload_file, $cus_name);
28-
return $file;
30+
// Cut original file name
31+
$file = explode('.', $filename);
32+
33+
if (empty($size) && \Storage::exists($this->basepath . $file[0] . '_L.' . $file[1])) {
34+
return $this->basepath . $file[0] . '_L.' . $file[1];
35+
} else if (\Storage::exists($this->basepath . $file[0] . '_' . $size . '.' . $file[1])) {
36+
return $this->basepath . $file[0] . '_' . $size . '.' . $file[1];
37+
} else {
38+
return $this->basepath . $filename;
39+
}
2940
}
3041

31-
private function moveFile($upload_file, $cus_name)
42+
public function thumbs($thumb_sizes = array())
3243
{
33-
$suffix = $upload_file->getClientOriginalExtension();
34-
$filename = uniqid() . '.' . $suffix;
35-
if (!empty($cus_name)) {
36-
$filename = $cus_name . '.' .$suffix;
37-
}
38-
39-
switch (\File::mimeType($upload_file)) {
40-
case 'image/jpeg':
41-
case 'image/jpg':
42-
$img = imagecreatefromjpeg($upload_file->getRealPath());
43-
$exif = read_exif_data($upload_file->getRealPath());
44-
if (isset($exif['Orientation'])) {
45-
switch ($exif['Orientation']) {
46-
case 8:
47-
$img = imagerotate($img, 90, 0);
48-
break;
49-
case 3:
50-
$img = imagerotate($img, 180, 0);
51-
break;
52-
case 6:
53-
$img = imagerotate($img, -90, 0);
54-
break;
55-
}
56-
}
57-
58-
imagejpeg($img, $upload_file->getRealPath());
44+
if (!empty($thumb_sizes)) {
45+
$this->thumb_sizes = $thumb_sizes;
5946
}
6047

61-
\Storage::put(
62-
$this->basepath . $filename,
63-
file_get_contents($upload_file->getRealPath())
64-
);
48+
return $this;
49+
}
6550

66-
\File::delete($upload_file->getRealPath());
67-
return $filename;
51+
public function crop()
52+
{
53+
$this->shouldCropThumb = true;
54+
55+
return $this;
56+
}
57+
58+
public function save(UploadedFile $upload_file, $cus_name = null)
59+
{
60+
$file = $this->moveFile($upload_file, $cus_name);
61+
return $file;
6862
}
6963

7064
public function getPath($filename)
@@ -74,7 +68,7 @@ public function getPath($filename)
7468
}
7569

7670
if (preg_match('/^\//', $filename)) {
77-
return $this->basepath . mb_substr($filename, 1, null, 'utf8');
71+
$filename = mb_substr($filename, 1, null, 'utf8');
7872
}
7973

8074
return $this->basepath . $filename;
@@ -122,4 +116,214 @@ public function getResponse($filename, $headers = [])
122116
abort(404);
123117
}
124118
}
119+
120+
public function drop($filename)
121+
{
122+
// Cut original file name
123+
$dot = strpos($filename, '.');
124+
$origin_name = substr($filename, 0, $dot);
125+
126+
// Find all images in basepath
127+
$allFiles = \Storage::files($this->basepath);
128+
$files = array_filter($allFiles, function ($file) use ($origin_name)
129+
{
130+
return preg_match('/^(.*)'.$origin_name.'(.*)$/', $file);
131+
});
132+
133+
// Delete original image and thumbnails
134+
foreach ($files as $file) {
135+
\Storage::delete($file);
136+
}
137+
}
138+
139+
/********************************************
140+
*********** Private Functions *************
141+
********************************************/
142+
143+
private function moveFile($upload_file, $cus_name)
144+
{
145+
$suffix = $upload_file->getClientOriginalExtension();
146+
147+
if (empty($cus_name)) {
148+
$original_name = uniqid();
149+
} else {
150+
$original_name = $cus_name;
151+
}
152+
$filename = $original_name . '.' .$suffix;
153+
154+
$img = $this->setTmpImage($upload_file);
155+
156+
\Storage::put(
157+
$this->basepath . $filename,
158+
file_get_contents($upload_file->getRealPath())
159+
);
160+
161+
\File::delete($upload_file->getRealPath());
162+
163+
if (!is_null($img) && !empty($this->getThumbSizes())) {
164+
$this->saveThumb($img, $original_name, $suffix);
165+
}
166+
167+
return $filename;
168+
}
169+
170+
private function setTmpImage($upload_file)
171+
{
172+
$image_types = array('image/png', 'image/gif', 'image/jpeg', 'image/jpg');
173+
174+
if (in_array(\File::mimeType($upload_file), $image_types)) {
175+
switch (\File::mimeType($upload_file)) {
176+
case 'image/png':
177+
$img = imagecreatefrompng($upload_file->getRealPath());
178+
break;
179+
case 'image/gif':
180+
$img = imagecreatefromgif($upload_file->getRealPath());
181+
break;
182+
case 'image/jpeg':
183+
case 'image/jpg':
184+
default:
185+
$img = imagecreatefromjpeg($upload_file->getRealPath());
186+
$exif = read_exif_data($upload_file->getRealPath());
187+
if (isset($exif['Orientation'])) {
188+
switch ($exif['Orientation']) {
189+
case 8:
190+
$img = imagerotate($img, 90, 0);
191+
break;
192+
case 3:
193+
$img = imagerotate($img, 180, 0);
194+
break;
195+
case 6:
196+
$img = imagerotate($img, -90, 0);
197+
break;
198+
}
199+
}
200+
}
201+
202+
imagepng($img, $upload_file->getRealPath());
203+
204+
return $img;
205+
} else {
206+
return null;
207+
}
208+
}
209+
210+
private function saveThumb($img, $original_name, $suffix)
211+
{
212+
foreach ($this->getThumbSizes() as $size_code => $size) {
213+
if (is_int($size_code) && $size_code < count($this->getThumbSizes())) {
214+
$size_name = 'L';
215+
} else {
216+
$size_name = $size_code;
217+
}
218+
219+
$thumb_name = $this->basepath . $original_name . '_' . $size_name . '.' . $suffix;
220+
$main_image = $original_name . '.' . $suffix;
221+
$tmp_filename = 'tmp/' . $main_image;
222+
223+
$tmp_thumb = $this->resizeOrCropThumb($img, $size);
224+
225+
// save tmp image
226+
\Storage::disk('local')->put($tmp_filename, \Storage::get($this->basepath . $main_image));
227+
$tmp_path = \Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix();
228+
229+
// save thumbnail image
230+
imagepng($tmp_thumb, $tmp_path . $tmp_filename);
231+
$tmp_file = \Storage::disk('local')->get($tmp_filename);
232+
\Storage::put($thumb_name, $tmp_file);
233+
234+
// remove tmp image
235+
\Storage::disk('local')->delete($tmp_filename);
236+
}
237+
}
238+
239+
private function resizeOrCropThumb($img, $size)
240+
{
241+
$width = imagesx($img);
242+
$height = imagesy($img);
243+
$arr_size = explode('x', $size);
244+
$thumb_width = (int)$arr_size[0];
245+
$thumb_height = (int)$arr_size[1];
246+
247+
if ($this->thumbShouldCrop()) {
248+
$img = $this->cropThumb($img, $width, $height, $thumb_width, $thumb_height);
249+
} else {
250+
$this->resizeThumb($width, $height, $thumb_width, $thumb_height);
251+
}
252+
253+
// create a new temporary thumbnail image
254+
$tmp_thumb = imagecreatetruecolor($thumb_width, $thumb_height);
255+
256+
// copy and resize original image into thumbnail image
257+
imagecopyresized($tmp_thumb, $img, 0, 0, 0, 0, $thumb_width, $thumb_height, $width, $height);
258+
259+
return $tmp_thumb;
260+
}
261+
262+
private function thumbShouldCrop()
263+
{
264+
return $this->shouldCropThumb;
265+
}
266+
267+
private function cropThumb($img, &$width, &$height, $thumb_width, $thumb_height)
268+
{
269+
$image_ratio = $height/$width;
270+
$thumb_ratio = $thumb_height/$thumb_width;
271+
272+
if ($image_ratio !== $thumb_ratio) {
273+
if ($image_ratio < $thumb_ratio) {
274+
$new_width = $thumb_width*$height/$thumb_height;
275+
276+
$square = [
277+
'x' => ($width - $new_width)/2,
278+
'y' => 0,
279+
'width' => $new_width,
280+
'height' => $height
281+
];
282+
283+
$width = $new_width;
284+
} else if ($image_ratio > $thumb_ratio) {
285+
$new_height = $thumb_height*$width/$thumb_width;
286+
287+
$square = [
288+
'x' => 0,
289+
'y' => ($height - $new_height)/2,
290+
'width' => $width,
291+
'height' => $new_height
292+
];
293+
294+
$height = $new_height;
295+
}
296+
297+
$img = imagecrop($img, $square);
298+
}
299+
300+
return $img;
301+
}
302+
303+
private function resizeThumb($width, $height, &$thumb_width, &$thumb_height)
304+
{
305+
$image_ratio = $height/$width;
306+
$thumb_ratio = $thumb_height/$thumb_width;
307+
308+
if ($image_ratio !== $thumb_ratio) {
309+
if ($image_ratio < $thumb_ratio) {
310+
$thumb_height = $thumb_width*$height/$width;
311+
} else if ($image_ratio > $thumb_ratio) {
312+
$thumb_width = $thumb_height*$width/$height;
313+
}
314+
}
315+
}
316+
317+
private function getThumbSizes()
318+
{
319+
$config = config('fileapi.default_thumbs');
320+
321+
if (!is_null($this->thumb_sizes)) {
322+
return $this->thumb_sizes;
323+
} else if (!is_null($config)) {
324+
return $config;
325+
} else {
326+
return $this->default_sizes;
327+
}
328+
}
125329
}

0 commit comments

Comments
 (0)