在 Django 中上传图像:'utf-8' 编解码器无法解码位置 246 中的字节 0x89:起始字节无效
Uploading Image in Django: 'utf-8' codec can't decode byte 0x89 in position 246: invalid start byte
我正在尝试使用纯 json 在我的 api 中上传图片,但是当我尝试在 request.Files 中上传图片并在 request.body 中上传令牌时,我遇到这个错误:
UnicodeDecodeError at /api/auth/set-profile-image/
'utf-8' codec can't decode byte 0x89 in position 246: invalid start byte
它说:
Unicode error hint
The string that could not be encoded/decoded was: " �PNG
但我发送的是 JPG! :D
View.py
@csrf_exempt
def set_profile_image(request):
if request.method == 'POST':
request_info = json.loads(request.body)
token = request_info.get('token')
img = request.FILES['image']
if token is not None and img is not None:
user = User.objects.filter(token=token)
if user.exists():
user = user.get()
form = UploadImage(request.POST, request.FILES['image'])
if form.is_valid():
user.profile_image = form.cleaned_data['image']
user.save()
response = {
'status_code': 200,
'image_set': True,
'image_url': user.profile_image.url
}
Form.py
from django import forms
class UploadImage(forms.Form):
image = forms.ImageField()
我的测试代码是:
import requests
data = {
'token': 'helloworld1--_aFsV-ZVG9lVpi0KSydrx3pG3TSMPqqHVKWD2Yc8bE'
}
url = 'http://localhost:8000/api/auth/set-profile-image/'
with open('test.jpg', 'rb') as img:
response = requests.post(
url=url,
data=data,
files={
'image': img
}
)
# print(response.text)
f = open('test.html', 'wb')
f.write(response.content)
f.close()
我在 models.py
中使用 ImageField
作为我的数据库字段
最热烈的问候,
可怜的维护人员,一直卡在别人的代码里!
图像将包含以 UTF-8 表示不安全的数据。如果您需要以这种方式传输图像数据,您应该先将其编码为其他在 UTF-8 中安全的东西,例如 base64。
要在您的 Python 发件人中执行此操作,您可以使用 base64.b64encode(img)
要在另一边再次解码,您需要使用base64.b64decode(img)
好的,经过一些测试并感谢 Jacob See 的回答,我找到了解决方案:
首先,我将我的图像编码为 base64,然后通过 API 发送它,如下所示:
with open('test.jpg', 'rb') as img:
data = {
"token": "some token"
}
response = requests.post(
url=url,
data={
'data': json.dumps(data),
'image': b64encode(img.read())
}
)
在我的 API 中,我这样做:
new_base64_img = request.POST.get('image', None)
try:
image = Image.open(BytesIO(b64decode(new_base64_img)))
image_content = ContentFile(b64decode(new_base64_img))
file_name = "some file name" + image.format
user.profile_image.save(file_name, image_content, save=True)
return JsonResponse({"OK"})
except IOError:
return JsonResponse({"Image should be base64 encoded!"})
问题已解决:D
我正在尝试使用纯 json 在我的 api 中上传图片,但是当我尝试在 request.Files 中上传图片并在 request.body 中上传令牌时,我遇到这个错误:
UnicodeDecodeError at /api/auth/set-profile-image/
'utf-8' codec can't decode byte 0x89 in position 246: invalid start byte
它说:
Unicode error hint
The string that could not be encoded/decoded was: " �PNG
但我发送的是 JPG! :D
View.py
@csrf_exempt
def set_profile_image(request):
if request.method == 'POST':
request_info = json.loads(request.body)
token = request_info.get('token')
img = request.FILES['image']
if token is not None and img is not None:
user = User.objects.filter(token=token)
if user.exists():
user = user.get()
form = UploadImage(request.POST, request.FILES['image'])
if form.is_valid():
user.profile_image = form.cleaned_data['image']
user.save()
response = {
'status_code': 200,
'image_set': True,
'image_url': user.profile_image.url
}
Form.py
from django import forms
class UploadImage(forms.Form):
image = forms.ImageField()
我的测试代码是:
import requests
data = {
'token': 'helloworld1--_aFsV-ZVG9lVpi0KSydrx3pG3TSMPqqHVKWD2Yc8bE'
}
url = 'http://localhost:8000/api/auth/set-profile-image/'
with open('test.jpg', 'rb') as img:
response = requests.post(
url=url,
data=data,
files={
'image': img
}
)
# print(response.text)
f = open('test.html', 'wb')
f.write(response.content)
f.close()
我在 models.py
中使用ImageField
作为我的数据库字段
最热烈的问候, 可怜的维护人员,一直卡在别人的代码里!
图像将包含以 UTF-8 表示不安全的数据。如果您需要以这种方式传输图像数据,您应该先将其编码为其他在 UTF-8 中安全的东西,例如 base64。
要在您的 Python 发件人中执行此操作,您可以使用 base64.b64encode(img)
要在另一边再次解码,您需要使用base64.b64decode(img)
好的,经过一些测试并感谢 Jacob See 的回答,我找到了解决方案:
首先,我将我的图像编码为 base64,然后通过 API 发送它,如下所示:
with open('test.jpg', 'rb') as img:
data = {
"token": "some token"
}
response = requests.post(
url=url,
data={
'data': json.dumps(data),
'image': b64encode(img.read())
}
)
在我的 API 中,我这样做:
new_base64_img = request.POST.get('image', None)
try:
image = Image.open(BytesIO(b64decode(new_base64_img)))
image_content = ContentFile(b64decode(new_base64_img))
file_name = "some file name" + image.format
user.profile_image.save(file_name, image_content, save=True)
return JsonResponse({"OK"})
except IOError:
return JsonResponse({"Image should be base64 encoded!"})
问题已解决:D