@@ -251,41 +251,31 @@ def delete_multiple_images(payload: dict):
251
251
},
252
252
)
253
253
path = os .path .normpath (path )
254
- parts = path .split (os .sep )
255
- if "images" in parts :
256
- parts .insert (parts .index ("images" ) + 1 , "PictoPy.thumbnails" )
257
- thumb_nail_image_path = os .sep .join (parts )
258
-
259
- if os .path .exists (thumb_nail_image_path ):
260
- print (f"Thumbnail found: { thumb_nail_image_path } " )
261
- else :
262
- print (f"Thumbnail not found: { thumb_nail_image_path } " )
263
- else :
264
- thumb_nail_image_path = ""
265
- print (f"'images' directory not found in path: { path } " )
254
+ folder_path , filename = os .path .split (path )
255
+ thumbnail_folder = os .path .join (folder_path , "PictoPy.thumbnails" )
256
+ thumb_nail_image_path = os .path .join (thumbnail_folder , filename )
266
257
267
-
268
- if os .path .exists (path ) :
269
- try :
258
+ # Check and remove the original file
259
+ if os .path .exists (path ):
260
+ try :
270
261
os .remove (path )
271
262
except PermissionError :
272
- print (f"Permission denied for file '{ thumb_nail_image_path } '." )
263
+ print (f"Permission denied for file '{ path } '." )
273
264
except Exception as e :
274
265
print (f"An error occurred: { e } " )
275
-
276
266
else :
277
267
print (f"File '{ path } ' does not exist." )
278
-
279
- if os .path .exists (thumb_nail_image_path ) :
280
- try :
268
+
269
+ # Check and remove the thumbnail file
270
+ if os .path .exists (thumb_nail_image_path ):
271
+ try :
281
272
os .remove (thumb_nail_image_path )
282
273
except PermissionError :
283
274
print (f"Permission denied for file '{ thumb_nail_image_path } '." )
284
275
except Exception as e :
285
276
print (f"An error occurred: { e } " )
286
- else :
277
+ else :
287
278
print (f"File '{ thumb_nail_image_path } ' does not exist." )
288
-
289
279
290
280
delete_image_db (path )
291
281
deleted_paths .append (path )
@@ -489,6 +479,98 @@ async def add_folder(payload: dict):
489
479
@router .post ("/generate-thumbnails" )
490
480
@exception_handler_wrapper
491
481
def generate_thumbnails (payload : dict ):
482
+ if "folder_paths" not in payload or not isinstance (payload ["folder_paths" ], list ):
483
+ return JSONResponse (
484
+ status_code = 400 ,
485
+ content = {
486
+ "status_code" : 400 ,
487
+ "content" : {
488
+ "success" : False ,
489
+ "error" : "Invalid or missing 'folder_paths' in payload" ,
490
+ "message" : "'folder_paths' must be a list of folder paths" ,
491
+ },
492
+ },
493
+ )
494
+
495
+ folder_paths = payload ["folder_paths" ]
496
+ image_extensions = [".jpg" , ".jpeg" , ".png" , ".bmp" , ".gif" , ".webp" ]
497
+ failed_paths = []
498
+
499
+ for folder_path in folder_paths :
500
+ if not os .path .isdir (folder_path ):
501
+ failed_paths .append (
502
+ {
503
+ "folder_path" : folder_path ,
504
+ "error" : "Invalid folder path" ,
505
+ "message" : "The provided path is not a valid directory" ,
506
+ }
507
+ )
508
+ continue
509
+
510
+ for root , _ , files in os .walk (folder_path ):
511
+ # Do not generate thumbnails for the "PictoPy.thumbnails" folder
512
+ if "PictoPy.thumbnails" in root :
513
+ continue
514
+
515
+ # Create the "PictoPy.thumbnails" folder in the current directory (`root`)
516
+ thumbnail_folder = os .path .join (root , "PictoPy.thumbnails" )
517
+ os .makedirs (thumbnail_folder , exist_ok = True )
518
+
519
+ for file in files :
520
+ file_path = os .path .join (root , file )
521
+ file_extension = os .path .splitext (file_path )[1 ].lower ()
522
+ if file_extension in image_extensions :
523
+ try :
524
+ # Create a unique thumbnail name based on the file name
525
+ thumbnail_name = file
526
+ thumbnail_path = os .path .join (thumbnail_folder , thumbnail_name )
527
+
528
+ # Skip if the thumbnail already exists
529
+ if os .path .exists (thumbnail_path ):
530
+ continue
531
+
532
+ # Generate the thumbnail
533
+ img = Image .open (file_path )
534
+ img .thumbnail ((400 , 400 ))
535
+ img .save (thumbnail_path )
536
+ except Exception as e :
537
+ failed_paths .append (
538
+ {
539
+ "folder_path" : folder_path ,
540
+ "file" : file_path ,
541
+ "error" : "Thumbnail generation error" ,
542
+ "message" : f"Error processing file { file } : { str (e )} " ,
543
+ }
544
+ )
545
+
546
+ if failed_paths :
547
+ return JSONResponse (
548
+ status_code = 207 , # Multi-Status (some succeeded, some failed)
549
+ content = {
550
+ "status_code" : 207 ,
551
+ "content" : {
552
+ "success" : False ,
553
+ "error" : "Partial processing" ,
554
+ "message" : "Some folders or files could not be processed" ,
555
+ "failed_paths" : failed_paths ,
556
+ },
557
+ },
558
+ )
559
+
560
+ return JSONResponse (
561
+ status_code = 201 ,
562
+ content = {
563
+ "data" : "" ,
564
+ "message" : "Thumbnails generated successfully for all valid folders" ,
565
+ "success" : True ,
566
+ },
567
+ )
568
+
569
+
570
+ # Delete all the thumbnails present in the given folder
571
+ @router .delete ("/delete-thumbnails" )
572
+ @exception_handler_wrapper
573
+ def delete_thumbnails (payload : dict ):
492
574
if "folder_path" not in payload :
493
575
return JSONResponse (
494
576
status_code = 400 ,
@@ -516,53 +598,47 @@ def generate_thumbnails(payload: dict):
516
598
},
517
599
)
518
600
519
- thumbnail_folder = os . path . join ( folder_path , "PictoPy. thumbnails" )
520
- os . makedirs ( thumbnail_folder , exist_ok = True )
601
+ # List to store any errors encountered while deleting thumbnails
602
+ failed_deletions = []
521
603
522
- image_extensions = [".jpg" , ".jpeg" , ".png" , ".bmp" , ".gif" , ".webp" ]
523
- for root , _ , files in os .walk (folder_path ):
524
- if "PictoPy.thumbnails" in root :
525
- continue
526
- for file in files :
527
- file_path = os .path .join (root , file )
528
- file_extension = os .path .splitext (file_path )[1 ].lower ()
529
- if file_extension in image_extensions :
604
+ # Walk through the folder path and find all `PictoPy.thumbnails` folders
605
+ for root , dirs , _ in os .walk (folder_path ):
606
+ for dir_name in dirs :
607
+ if dir_name == "PictoPy.thumbnails" :
608
+ thumbnail_folder = os .path .join (root , dir_name )
530
609
try :
531
- # Create a unique name based on the relative folder structure
532
- relative_path = os .path .relpath (root , folder_path )
533
- sanitized_relative_path = relative_path .replace (
534
- os .sep , "."
535
- ) # Replace path separators
536
- thumbnail_name = (
537
- f"{ sanitized_relative_path } .{ file } "
538
- if relative_path != "."
539
- else file
540
- )
541
- thumbnail_path = os .path .join (thumbnail_folder , thumbnail_name )
542
- if os .path .exists (thumbnail_path ):
543
- # print(f"Thumbnail {thumbnail_name} already exists. Skipping.")
544
- continue
545
- img = Image .open (file_path )
546
- img .thumbnail ((400 , 400 ))
547
- img .save (thumbnail_path )
610
+ # Delete the thumbnail folder
611
+ shutil .rmtree (thumbnail_folder )
612
+ print (f"Deleted: { thumbnail_folder } " )
548
613
except Exception as e :
549
- return JSONResponse (
550
- status_code = 500 ,
551
- content = {
552
- "status_code" : 500 ,
553
- "content" : {
554
- "success" : False ,
555
- "error" : "Internal server error" ,
556
- "message" : f"Error processing file { file } : { str (e )} " ,
557
- },
558
- },
614
+ failed_deletions .append (
615
+ {
616
+ "folder" : thumbnail_folder ,
617
+ "error" : str (e ),
618
+ }
559
619
)
560
620
621
+ if failed_deletions :
622
+ return JSONResponse (
623
+ status_code = 500 ,
624
+ content = {
625
+ "status_code" : 500 ,
626
+ "content" : {
627
+ "success" : False ,
628
+ "error" : "Some thumbnail folders could not be deleted" ,
629
+ "message" : "See the `failed_deletions` field for details." ,
630
+ "failed_deletions" : failed_deletions ,
631
+ },
632
+ },
633
+ )
634
+
561
635
return JSONResponse (
562
- status_code = 201 ,
636
+ status_code = 200 ,
563
637
content = {
564
- "data" : "" ,
565
- "message" : "Thumbnails generated successfully" ,
566
- "success" : True ,
638
+ "status_code" : 200 ,
639
+ "content" : {
640
+ "success" : True ,
641
+ "message" : "All PictoPy.thumbnails folders have been successfully deleted." ,
642
+ },
567
643
},
568
644
)
0 commit comments