You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django接口出现UnicodeDecodeError,如何返回图片URL?

问题与解决方案

问题说明

目标是在接口响应中返回图片URL,但直接返回request.data.get('img')触发UnicodeDecodeError,报错核心原因是无法解码图片的二进制字节(以0xff开头,属于图片文件原始二进制数据)。

为什么不能直接返回request.data.get('img')?

request.data.get('img')获取到的是二进制文件对象(InMemoryUploadedFile类型),并非字符串格式的URL。DRF在序列化响应内容时,会尝试将该二进制对象转换为UTF-8编码的字符串,而图片二进制数据不符合UTF-8编码规则,因此触发解码错误。

解决方案

要返回图片URL,需先将上传的图片保存到服务器指定位置,再生成对应的可访问URL返回。以下是两种可行实现方式:

方式一:使用Django模型存储图片(推荐)

  1. 定义模型存储图片字段:
# models.py
from django.db import models

class Image(models.Model):
    img = models.ImageField(upload_to='images/')  # 图片将保存到MEDIA_ROOT/images/目录下
  1. 修改Serializer为ModelSerializer,新增URL生成逻辑:
# serializer.py
from rest_framework import serializers
from .models import Image

class ImageSerializer(serializers.ModelSerializer):
    img_url = serializers.SerializerMethodField()

    def get_img_url(self, obj):
        # 生成图片的完整访问URL
        return self.context['request'].build_absolute_uri(obj.img.url)

    class Meta:
        model = Image
        fields = ['img', 'img_url']
  1. 修改视图逻辑,验证并保存图片后返回URL:
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializer import ImageSerializer

class ImageView(APIView):
    def post(self, request):
        serializer = ImageSerializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return Response(
                {"processed_image_data": serializer.data['img_url']},
                status=status.HTTP_200_OK
            )
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

方式二:手动保存图片(不依赖数据库模型)

若无需数据库存储,可手动将图片保存到服务器目录,再拼接URL返回:

# views.py
import os
from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializer import ImageSerializer

class ImageView(APIView):
    def post(self, request):
        serializer = ImageSerializer(data=request.data)
        if serializer.is_valid():
            img_file = request.FILES.get('img')
            if img_file:
                # 创建保存目录(不存在则自动生成)
                save_dir = os.path.join(settings.MEDIA_ROOT, 'images')
                os.makedirs(save_dir, exist_ok=True)
                # 写入图片文件
                file_path = os.path.join(save_dir, img_file.name)
                with open(file_path, 'wb+') as f:
                    for chunk in img_file.chunks():
                        f.write(chunk)
                # 生成可访问URL
                img_url = request.build_absolute_uri(f'/media/images/{img_file.name}')
                return Response(
                    {"processed_image_data": img_url},
                    status=status.HTTP_200_OK
                )
            return Response({"error": "未提供图片文件"}, status=status.HTTP_400_BAD_REQUEST)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

必备配置

无论采用哪种方式,都需要在Django配置文件settings.py中添加媒体文件相关配置:

# settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

同时在项目根路由urls.py中添加媒体文件访问路由:

# urls.py
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path

urlpatterns = [
    # 其他业务路由...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

内容的提问来源于stack exchange,提问作者Mossaddak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:52:40