Джанго Твипи не может получить доступ к файлу Amazon S3

Я использую Tweepy, библиотеку Python для твитов, django-storages и boto. У меня есть пользовательская команда manage.py, которая корректно работает локально, она получает изображение из файловой системы и отправляет это изображение в Твиттер. Однако если я изменю хранилище на Amazon S3, я не смогу получить доступ к файлу. Это дает мне эту ошибку:

 raise TweepError('Unable to access file: %s' % e.strerror)

Я попытался сделать изображения в ведре «общедоступными». Не работает. Это код (он работает без S3):

filename = model_object.image.file.url
media_ids = api.media_upload(filename=filename)  # ERROR

params = {'status': tweet_text, 'media_ids': [media_ids.media_id_string]}
api.update_status(**params)

Эта строка:

model_object.image.file.url

Дает мне полный URL-адрес изображения, которое я хочу твитнуть, примерно так:

https://criptolibertad.s3.amazonaws.com/OrillaLibertaria/195.jpg?Signature=xxxExpires=1467645897&AWSAccessKeyId=yyy

Я также попытался создать URL-адрес вручную, так как это общедоступное изображение, хранящееся в моей корзине, например:

filename = "https://criptolibertad.s3.amazonaws.com/OrillaLibertaria/195.jpg"

Но это не работает.

¿Почему я получаю ошибку Unable to access file?

Исходный код от tweepy выглядит так:

def media_upload(self, filename, *args, **kwargs):
    """ :reference: https://dev.twitter.com/rest/reference/post/media/upload
        :allowed_param:
    """
    f = kwargs.pop('file', None)
    headers, post_data = API._pack_image(filename, 3072, form_field='media', f=f)  # ERROR
    kwargs.update({'headers': headers, 'post_data': post_data})


def _pack_image(filename, max_size, form_field="image", f=None):
        """Pack image from file into multipart-formdata post body"""
        # image must be less than 700kb in size
        if f is None:
            try:
                if os.path.getsize(filename) > (max_size * 1024):
                    raise TweepError('File is too big, must be less than %skb.' % max_size)
            except os.error as e:
                raise TweepError('Unable to access file: %s' % e.strerror)

Похоже, Tweepy не может получить образ из корзины Amazon S3, но как заставить его работать? Любой совет поможет.


person Alejandro Veintimilla    schedule 30.06.2016    source источник
comment
URL - это метод, а не атрибут.   -  person Burhan Khalid    schedule 01.07.2016
comment
@BurhanKhalid, как мне это назвать? Если я делаю model_object.image.file.url(), я получаю сообщение об ошибке: 'S3BotoStorageFile' object has no attribute 'url'   -  person Alejandro Veintimilla    schedule 01.07.2016
comment
@BurhanKhalid работает как такой атрибут: model_object.image.url . Это дает мне полный URL-адрес изображения. Но я все равно получаю ошибку: Unable to access file.   -  person Alejandro Veintimilla    schedule 01.07.2016


Ответы (1)


Проблема возникает, когда tweepy пытается получить размер файла в _pack_image:

if os.path.getsize(filename) > (max_size * 1024):

Функция os.path.getsize предполагает, что ей задан путь к файлу на диске; однако в вашем случае ему дается URL-адрес. Естественно файл на диске не найден и ставится os.error. Например:

# The following raises OSError on my machine
os.path.getsize('https://criptolibertad.s3.amazonaws.com/OrillaLibertaria/195.jpg')

Что вы можете сделать, так это получить содержимое файла, временно сохранить его локально, а затем твитнуть:

import tempfile


with tempfile.NamedTemporaryFile(delete=True) as f:
    name = model_object.image.file.name
    f.write(model_object.image.read())
    media_ids = api.media_upload(filename=name, f=f)
    params = dict(status='test media', media_ids=[media_ids.media_id_string])
    api.update_status(**params)

Для вашего удобства я опубликовал полностью рабочий пример здесь: https://github.com/izzysoftware/so38134984.

person tutuDajuju    schedule 04.07.2016
comment
Спасибо за твой ответ, братан. У меня есть проблема. Я пытался в течение нескольких часов, чтобы сделать эту работу. Мой код теперь такой же, как у вас, однако я все еще получаю сообщение об ошибке Unable to access file . Вы можете увидеть весь мой проект в этом репозитории, и точные строки здесь: github.com/Alejoss/CrHisoka/blob/master/hisoka/management/ . Почему я получаю ошибку? Я понятия не имею. Но я подозреваю, что f это None после f.write(model_object.image.read()). Любые идеи? - person Alejandro Veintimilla; 06.07.2016
comment
я не думаю, что f может быть none; может он пустой? Ваш код выглядит надежно, я постараюсь проверить его сегодня вечером и попробовать. Вы можете проверить, что у вашего пользователя aws есть разрешения s3 по мере необходимости. - person tutuDajuju; 06.07.2016
comment
Мне удалось использовать ваш код для загрузки мультимедиа и твитов, см. подробности в PR здесь: github. com/Alejoss/CrHisoka/pull/1 . - person tutuDajuju; 06.07.2016