pythonflaskazure-storage-filesazure-file-share

How to zip all the files under azure storage file share and send the zip as response?


I am trying to make a route in flask which zips all the files under file share home directory and sends the zip as response. The code I have has some issue but I am not sure what is wrong here. The response is received by reactJS to download the zip.

@files_blueprint.route('/download/all', methods=['GET'])
def download_all():
    print("-------------downloading all files-----------")
    parent_dir = ShareDirectoryClient.from_connection_string(conn_str=connection_string, share_name=my_share, directory_path="")

    my_list = list(parent_dir.list_directories_and_files())
    print(my_list[0])

    # Get a reference to the file share
    share_client = service.get_share_client(file_share_name)

    # Create a temporary directory to store the zip file
    temp_dir = '/tmp'
    os.makedirs(temp_dir, exist_ok=True)

    # Create a zip archive containing all the files from the root directory of the share
    zip_filename = 'zipped_share.zip'
    with ZipFile(os.path.join(temp_dir, zip_filename), 'w') as zipf:
        for file in share_client.get_directory_client('').list_directories_and_files():
            file_name = file.name
            file_path = os.path.join(temp_dir, file_name)
            file_client = share_client.get_file_client(file_name)
            with open(file_path, 'wb') as local_file:
                file_client.download_file().readinto(local_file)
            zipf.write(file_path, file_name)

    # Send the zip file as a response
    response = send_file(os.path.join(temp_dir, zip_filename), as_attachment=True)

    # Clean up the temporary directory and files
    shutil.rmtree(temp_dir)

    return response


Solution

  • How to zip all the files under Azure storage file share and send the zip as a response?

    You can use the below Python code to route in Flask the list of files & download them as a zip folder and send them reactJS application.

    Code:

    from flask import Flask, send_file
    import os
    from zipfile import ZipFile
    import shutil
    from azure.storage.fileshare import ShareDirectoryClient
    from flask_cors import CORS 
    
    app = Flask(__name__)
    
    
    connection_string = "xxxx"
    my_share = "xxxxx"
    
    CORS(app, resources={r"/download/all": {"origins": "http://localhost:3000"}}) 
    
    @app.route('/download/all', methods=['GET'])
    def download_all():
        try:
            
            temp_dir = '/tmp'
            os.makedirs(temp_dir, exist_ok=True)
    
            
            share_directory = ShareDirectoryClient.from_connection_string(connection_string, my_share, directory_path="")
    
            zip_filename = 'zipped_share.zip'
            with ZipFile(os.path.join(temp_dir, zip_filename), 'w') as zipf:
                for file in share_directory.list_directories_and_files():
                    file_name = file.name
                    file_path = os.path.join(temp_dir, file_name)
                    file_client = share_directory.get_file_client(file_name)
                    with open(file_path, 'wb') as local_file:
                        file_client.download_file().readinto(local_file)
                    zipf.write(file_path, file_name)
    
            
            response = send_file(os.path.join(temp_dir, zip_filename), as_attachment=True)
    
            shutil.rmtree(temp_dir, ignore_errors=True)
    
            return response
    
        except Exception as e:
            return str(e), 500
    
    if __name__ == '__main__':
         app.run(host='0.0.0.0', port=5000)
    

    The above code downloads the list of files from Azure file share saves it as a zip sends it to the react app and deletes the temporary path.

    In react app under the src folder the App.js is like

    App.js

    import React from 'react';
    
    function App() {
      const downloadFiles = () => {
        
        fetch('http://127.0.0.1:5000/download/all')  // Replace with the actual Flask app URL
          .then(response => {
            // Check if the response is successful (status code 200)
            if (response.status === 200) {
              // Convert the response to a blob
              return response.blob();
            } else {
              throw new Error('Failed to download files');
            }
          })
          .then(blob => {
            // Create a URL for the blob
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'zipped_share.zip';  // The desired file name
            a.click();
            window.URL.revokeObjectURL(url);
          })
          .catch(error => {
            console.error(error);
          });
      };
    
      return (
        <div>
          <h1>Download All Files</h1>
          <button onClick={downloadFiles}>Download All Files</button>
        </div>
      );
    }
    
    export default App;
    

    My flask app output:

    enter image description here

    Front end output: enter image description here

    Atlast in browser:

    enter image description here