How to delete directories

Mounir
Mounir Member Posts: 10
edited September 17 in Developer APIs

Do I need to make any other settings in my Cloudinary account to have permission to delete directories?

Comments

  • atdatu
    atdatu Member, Cloudinary Staff Posts: 17

    Hi,

    There's like a media asset in the directory which prevents folder deletion. I would recommend to go to the Bulk delete in the Settings Page, choose to delete the following settings:
    1. Original and Derive

    2. Prefix: <folder name>

    3. Resource Type: <all> and Type: <all>

    Once the bulk delete is completed, proceed back to the folder and you should be able to delete it.

  • Mounir
    Mounir Member Posts: 10

    I have no problem with manually deleting the directories I created.
    My question is how to do them with the api.

  • Tom
    Tom Member, Cloudinary Staff Posts: 103

    Hi @Mounir ,

    Thanks for replying.

    You can use the Delete folder from folders API but as Anthony mentioned, the folder has to be empty or we won't delete it.

    You can use Delete resources to empty the folder first.

    Please let me know if you have any other questions or queries.

    Kind Regards,

    Thomas

  • Mounir
    Mounir Member Posts: 10
    edited September 16

    I used the code that cloudinary AI gave me and it didn't work.

    final folder = 'My empty directory in Cloudinary';
    const apiKey = '………………';
    const apiSecret = '………………';
    const cloudName = '………………';
    
    final url = Uri.parse('https://api.cloudinary.com/v1_1/$cloudName/folders/$folder');
    final response = await http.delete(url, headers: {'Authorization': 'Basic ${base64Encode(utf8.encode('$apiKey:$apiSecret'))}'});
    

  • Cloudinary_John_H
    Cloudinary_John_H Cloudinary Staff Posts: 47

    Hi @Mounir ,

    What error response are you getting back when you run that code? Is the "folder" value set the correct directory name?

    Thanks,
    John

  • Mounir
    Mounir Member Posts: 10

    I wrote a small flutter app just to try to delete an empty directory from cloudinary. The code for the delete function, I took it from cloudinary AI :

    final url = Uri.parse('https://api.cloudinary.com/v1_1/$cloudName/folders/$folderName');
    http.Response response;
    response = await http.delete(url, headers: {'Authorization': 'Basic ${base64Encode(utf8.encode('$apiKey:$apiSecret'))}'});
    

    When I run this app on windows and mobile platform, it works fine without any problem; the empty directory is indeed deleted.

    But when I run it on web platform, I have this message when deleting an empty directory:

    exception when delete folder: ClientException: XMLHttpRequest error., uri=https://api.cloudinary.com/v1_1/de8aab6a3/folders/empty
    

    Here is the full code of the app:

    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    import 'package:flutter/foundation.dart';
    import 'dart:convert';
    import 'mes_cle.dart';
    import 'dart:io';
    
    const apiKey = fCloudinaryApiKey;
    const apiSecret = fCloudinaryApiSecret;
    const cloudName = fCloudinaryCloudName;
    
    // Classe pour gérer les problèmes de certificats SSL sur Windows
    class MyHttpOverrides extends HttpOverrides {
      @override
      HttpClient createHttpClient(SecurityContext? context) {
        return super.createHttpClient(context)
          ..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
      }
    }
    
    void main() {
      // Désactiver la vérification du certificat SSL uniquement sur Windows (pour les tests)
      if (!kIsWeb && Platform.isWindows) {
        HttpOverrides.global = MyHttpOverrides();
      }
    
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Delete directory from Cloudinary',
          theme: ThemeData(
            colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrangeAccent),
            useMaterial3: true,
          ),
          home: const MyHomePage(title: 'Delete directory from Cloudinary'),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key, required this.title});
    
      final String title;
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
    
      final TextEditingController _directoryController = TextEditingController();
    
      Future<void> deleteDir() async {
    
        final folderName = _directoryController.text;
    
        try {
    
          final url = Uri.parse('https://api.cloudinary.com/v1_1/$cloudName/folders/$folderName');
          http.Response response;
          response = await http.delete(url, headers: {'Authorization': 'Basic ${base64Encode(utf8.encode('$apiKey:$apiSecret'))}'});
    
          print('URL de suppression : $url');
          print('Réponse de suppression : ${response.body}');
    
          if (response.statusCode == 200) {
            print('Folder deleted successfully');
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Folder deleted successfully')),
            );
          } else {
            print('Failed to delete folder: ${response.body}');
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Failed to delete folder')),
            );
          }
        } catch (e) {
          print('exception when delete folder: $e');
          ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text('exception when delete folder: $e')),
          );
        }
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            backgroundColor: Theme.of(context).colorScheme.inversePrimary,
            title: Text(widget.title),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  width: 200,
                  child: TextField(
                    controller: _directoryController,
                    decoration: InputDecoration(
                      hintText: 'Enter the directory to delete',
                    ),
                  ),
                ),
                SizedBox(height: 10),
                ElevatedButton(
                  onPressed: deleteDir,
                  child: Text('Delete directory'),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    

    And here is its appearance:
    https://mysite-4439f.web.app/

  • Tom
    Tom Member, Cloudinary Staff Posts: 103

    Hi @Mounir ,

    Thanks for replying.

    So in the error response, the API URL is https://api.cloudinary.com/v1_1/de8aab6a3/folders/empty .

    Is empty actually a folder name in your account?

    I look forward to your response. 

    Thomas

  • Mounir
    Mounir Member Posts: 10

    Yes of course; "empty" is an empty directory in my account. I left it empty for testing.

  • Tom
    Tom Member, Cloudinary Staff Posts: 103

    Hi @Mounir ,

    Thanks for confirming.

    So if you look at the console log, the error is:

    Access to XMLHttpRequest at 'https://api.cloudinary.com/v1_1/../folders/empty' from origin 'https://mysite-4439f.web.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.Understand this error
    main.dart.js:21857 
    

    It looks like you are making the call to our Admin API on the client side but we do not allow this which is the reason for the CORS error.

    We recommend routing the request to your own backend server and your server can relay the response back to the client.

    Please let me know if you have any other questions or queries.

    Kind Regards,

    Thomas

  • Mounir
    Mounir Member Posts: 10
    edited September 18

    Thanks a lot for the answer, Thomas.

    🙂