88class 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