Как использовать REST API Get File Properties для хранилища файлов Azure с использованием Python - PullRequest
0 голосов
/ 28 января 2019

Я пытаюсь создать скрипт Python, который будет использовать Python SDK для Azure и REST API для извлечения информации для файлов в моей учетной записи хранения файлов Azure.

Я использую SDK для доступа к файлам в хранилище и получения имен.Затем, используя имя, я хочу иметь возможность вызова API REST для получения свойств файла, в частности свойства Last-Modified.Я пытаюсь получить доступ к последнему измененному свойству с помощью SDK, но по какой-то причине оно всегда возвращает None.

Я хочу использовать дату последнего изменения, чтобы определить, прошло ли оно более 24 часов, а затемхочу удалить файл.Я не уверен, возможно ли установить какое-либо автоматическое удаление после определенного свойства периода в файле, когда я впервые создаю и загружаю его в Azure.Если есть, то это все равно решит мои проблемы.

Я разместил код, который использую ниже.Когда я пытаюсь сделать HTTP-запрос, я получаю сообщение об ошибке «Серверу не удалось аутентифицировать запрос. Убедитесь, что значение заголовка авторизации сформировано правильно, включая подпись».

    import datetime
    import requests
    import json
    import base64
    import hmac
    import hashlib
    import urllib
    from azure.storage.file import *

StorageAccountConnectionString = ""
fileshareName = "testFileShare"
storage_account_name = "testStorage"
storage_account_key = ""
api_version = "2018-03-28"

        file_service = FileService(connection_string=StorageAccountConnectionString)
    listOfStateDirectories = file_service.list_directories_and_files(fileshareName)

    for state_directory in listOfStateDirectories:
        print("Cleaning up State Directory: " + state_directory.name)
        if(isinstance(state_directory, Directory)):
            listOfBridgeDirectories = file_service.list_directories_and_files(fileshareName, state_directory.name)
            for bridge_directory in listOfBridgeDirectories:
                if(isinstance(bridge_directory, Directory)):
                    print("Cleaning up Bridge Directory: " + bridge_directory.name)
                    path_to_bridge_directory = state_directory.name + "/" + bridge_directory.name
                    listOfFilesAndFolders = file_service.list_directories_and_files(fileshareName, path_to_bridge_directory)

                for file_or_folder in listOfFilesAndFolders:
                    if isinstance(file_or_folder, File):
                        name_of_file = file_or_folder.name

                        # Get the time of the current request
                        request_time = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')

                        string_to_append_to_url = fileshareName + '/' + path_to_bridge_directory + '/' + name_of_file
                        # Parse the url to make sure everything is good
                        # string_to_append_to_url = urllib.parse.quote(string_to_append_to_url)

                        string_params = {
                            'verb': 'HEAD',
                            'Content-Encoding': '',
                            'Content-Language': '',
                            'Content-Length': '',
                            'Content-MD5': '',
                            'Content-Type': '',
                            'Date': '',
                            'If-Modified-Since': '',
                            'If-Match': '',
                            'If-None-Match': '',
                            'If-Unmodified-Since': '',
                            'Range': '',
                            'CanonicalizedHeaders': 'x-ms-date:' + request_time + '\nx-ms-version:' + api_version + '\n',
                            'CanonicalizedResource': '/' + storage_account_name + '/' + string_to_append_to_url
                        }

                        string_to_sign = (string_params['verb'] + '\n'
                                          + string_params['Content-Encoding'] + '\n'
                                          + string_params['Content-Language'] + '\n'
                                          + string_params['Content-Length'] + '\n'
                                          + string_params['Content-MD5'] + '\n'
                                          + string_params['Content-Type'] + '\n'
                                          + string_params['Date'] + '\n'
                                          + string_params['If-Modified-Since'] + '\n'
                                          + string_params['If-Match'] + '\n'
                                          + string_params['If-None-Match'] + '\n'
                                          + string_params['If-Unmodified-Since'] + '\n'
                                          + string_params['Range'] + '\n'
                                          + string_params['CanonicalizedHeaders']
                                          + string_params['CanonicalizedResource'])

                        signed_string = base64.b64encode(hmac.new(base64.b64decode(storage_account_key), msg=string_to_sign.encode('utf-8'), digestmod=hashlib.sha256).digest()).decode()

                        headers = {
                            'x-ms-date': request_time,
                            'x-ms-version': api_version,
                            'Authorization': ('SharedKey ' + storage_account_name + ':' + signed_string)
                        }

                        url = ('https://' + storage_account_name + '.file.core.windows.net/' + string_to_append_to_url)
                        print(url)


                        r = requests.get(url, headers=headers)
                        print(r.content)

ПРИМЕЧАНИЕ. Некоторые каталогибудет иметь пробелы, поэтому я не уверен, влияет ли это на вызов API REST, потому что в URL также будут пробелы.Если это повлияет, то как мне получить доступ к тем файлам, URL которых будут содержать пробелы

1 Ответ

0 голосов
/ 29 января 2019

Я пытаюсь получить доступ к последнему измененному свойству с помощью SDK, но по какой-то причине оно всегда возвращает None.

Не все API SDK и REST API возвращают свойство Last-Modifiedв заголовках ответа, которые включают REST API List Directories and Files и Python SDK API list_directories_and_files.

Я попытался воспроизвести вашу проблему с помощью SDK, так каккод ниже.

generator = file_service.list_directories_and_files(share_name, directory_name)
for file_or_dir in generator:
    if isinstance(file_or_dir, File):
        print(file_or_dir.name, file_or_dir.properties.last_modified)

Из-за метода list_directories_and_files не будет возвращено никаких свойств объекта File, поэтому значение file_or_dir.properties.last_modified приведенного выше кода равно None.

API REST Get File, Get File Properties, Get File Metadata и API Python SDK get_file_properties,get_file_metadata вернет свойство Last-Modified в заголовках ответа, поэтому измените код, как показано ниже, чтобы получить свойство last_modified, чтобы оно работало.

generator = file_service.list_directories_and_files(share_name, directory_name)
for file_or_dir in generator:
    if isinstance(file_or_dir, File):
        file_name = file_or_dir.name
        file = file_service.get_file_properties(share_name, directory_name, file_name, timeout=None, snapshot=None)
        print(file_or_dir.name, file.properties.last_modified)

Конечно, вызывать REST API так же, как использовать SDK API.Тем не менее, для создания строки подписи SAS легко допускать ошибки и неудобно читать код.

...