Django S3 : Ошибка UnicodeDecodeError: кодек ‘utf-8’ не может декодировать байт 0xff в позиции 0: недопустимый начальный байт

#python #django #amazon-s3 #utf-8 #byte

Вопрос:

Я пытаюсь использовать s3 для извлечения изображений на своем веб-сайте.

Я пытаюсь использовать get_object() для доступа к объекту изображения.

Часть объекта, которую я хочу вернуть, — это тело, тип которого-StreamingBody. Я хочу преобразовать StreamingBody в строку, чтобы вернуть его.

Вот мой код :

 @api_view(['GET'])
def get_image(request, image):
    """Get image link"""
    key = "media/"   str(image)
    s3 = boto3.client('s3', config=Config(signature_version='s3v4', region_name=settings.AWS_S3_REGION_NAME))
    obj = s3.get_object(Bucket=settings.AWS_STORAGE_BUCKET_NAME, Key=key)
    
    return Response(obj['Body'].read().decode('utf-8'))
 

urls.py

 from django.urls import path
from store import views

urlpatterns = [
    path('images/<str:image>', views.get_image),
]
 

obj['Body'].read() возвращаемые байты, которые я пытаюсь декодировать в utf-8.

Когда я запускаю obj['Body'].read().decode('utf-8') , я получаю эту ошибку : Ошибка UnicodeDecodeError: кодек ‘utf-8’ не может декодировать байт 0xff в позиции 0: недопустимый начальный байт

Заранее благодарю вас за вашу помощь

Обновить

Мне пришлось вернуть данные изображения в виде HttpResponse и без кодирования :

 image_data = obj['Body'].read()    
return HttpResponse(image_data, content_type="image/jpeg")
 

Комментарии:

1. Если это изображение, то, скорее всего, это двоичные данные, а не текст. Предполагается ли, что этот метод возвращает данные изображения или ссылку на изображение?

2. @IainShelvington, я пытаюсь вернуть данные изображения

3. Для чего будут использоваться эти данные? Я все равно не думаю, что тебе нужен звонок .decode

4. @IainShelvington Мне нужно создать конечную точку, которая обслуживает изображения. Если я не позвоню .decode , я получу эту ошибку : 'bytes' object has no attribute 'read'

5. Я думаю, что бы ни вызывало эту функцию, она ожидает, что будет возвращен файлоподобный объект, так как он ищет «чтение», возможно, вам просто нужно вернуться return obj['Body']

Ответ №1:

Это зависит от того, что именно вы хотите сделать:

Отобразить изображение:

 from django.http import HttpResponse
from rest_framework.decorators import api_view


@api_view(['GET'])
def get_image(request, image):
    ...
    
    data = obj['Body'].read()

    return HttpResponse(data, content_type=obj["ContentType"])
 

base64 URL-адрес для отображения данных

 import base64

from django.http import HttpResponse
from rest_framework.decorators import api_view


@api_view(['GET'])
def get_image(request, image):
    ...
    
    data = obj['Body'].read()
    base64_data = base64.b64encode(data).decode("utf-8")

    return HttpResponse(f'<img src="data:{obj["ContentType"]};base64,{base64_data}">')
 

Похоже, вы используете фреймворк Django REST, поэтому, если вы хотите вернуть JSON, вам придется кодировать его bas64 , например, с помощью:

 import base64

from rest_framework.decorators import api_view
from rest_framework.response import Response


@api_view(['GET'])
def get_image(request, image):
    ...
    
    data = obj['Body'].read()
    base64_data = base64.b64encode(data).decode("utf-8")

    return Response(base64_data)