【问题标题】:Encode/decode image to base64 flask&python将图像编码/解码为 base64 flask&python
【发布时间】:2021-01-07 18:26:27
【问题描述】:

我有一个名为“image.png”的图像,首先我向我的服务器发出请求,将图像保存为 json 文件中的 base64 字符串。

def get_img_content(coding='utf-8'):
    with open('image.png', 'rb') as f:
        img_data = base64.b64encode(f.read()).decode(coding)
        return img_data

requests.get(f'http://127.0.0.1:5000/?face={get_img_content()}')

下面我添加了处理我的请求的服务器代码

from flask import Flask, request
import os
import json

app = Flask(__name__)

if "data.json" not in os.listdir(os.getcwd()):
    with open('data.json', 'a', encoding='utf-8') as f:
        pass
    content = {'ids': [], 'results': []}
else:
    with open('data.json', 'r', encoding='utf-8') as f:
        content = json.loads(f.read())

def add_id(id, face, content=content):
    content['ids'].append({id: face})
    with open('data.json', 'w', encoding='utf-8') as f:
        f.write(json.dumps(content))

@app.route('/', methods=['GET'])
def main():
    face = request.args.get('face')
    if not face:
        return 'Valid request has to contain face'
    id = [int(list(i.keys())[0]) for i in content['ids']]
    id = str(max(id) + 1 if id else 1)
    add_id(id, face)
    print(content)
    return id


@app.route('/get', methods=['GET'])
def get():
    id = request.args.get('id')
    if not id:
        return 'Valid request has to contain id'
    for i in content['results']:
        if list(i.keys())[0] == id:
            return json.dumps({'result': i[id]})
    return "Couldn't find result"


if __name__ == '__main__':
    app.run()

之后我尝试从 data.json 读取这个 base64 字符串并将其转换为图像,但我得到了 PaddingError
binascii.Error: Incorrect padding

import base64
import json

with open('data.json', 'r', encoding='utf-8') as f:
    content = json.loads(f.read())


def to_image():
    with open('image.png', 'wb') as f:
        f.write(base64.b64decode(list(content['ids'][0].items())[-1][-1].encode('utf-8')))


to_image()

请帮助我重现我的步骤而不出现此错误。

【问题讨论】:

  • 您将 b64 字符串解码为 utf-8 做什么?
  • @Evgeniy,获取字符串并通过flask将其写入data.json。基数 64。 b64encode 返回字节。
  • 每种格式都有自己的“标题”和“结尾”(我认为),以便了解它包含什么类型的信息,数据从哪里开始以及在哪里结束。我调试了您的代码,您在 data.json 中写入的字节数组远小于图像中的原始字节数组......您正在丢失信息

标签: python json flask base64


【解决方案1】:

简介

每种格式都有(应该有)自己的“标题”和“结束”信号以便了解:

  1. 它包含什么类型的信息
  2. 数据从哪里开始。
  3. 结束的地方。

在此处查看 .jpg 文件的“标题”和“结尾”结构:JPG Signature Format: Documentation & Recovery Example

为什么会存在?它可以防止这里发生的事情……应该有一个“隐藏”代码来检查“标题”和“结束”字节是否正确,如果不正确,则数据已丢失。然后提醒您:

binascii.Error: 不正确的填充

调试

您在 data.json 中写入的字节数组远少于图像中的原始字节数组...您正在丢失信息。

观察

我看到的问题是,您正在使用 HTTP 动词 GET 发送大量数据。它有 8KB 的限制容量。然后,如果您的图像大于您无法使用 GET 请求发送它。

在此处查看限制:Maximum length of HTTP GET request

推荐

对于这种情况,使用 POST 请求发送大于 8KB 的数据(*使用 POST 请求不仅限于大小,还有其他情况)

解决方案

有多种方法可以通过 POST 请求发送,请参见此处:MIME types

发送:

  1. 一个图像,使用 MIME 类型image
  2. 多个文件与multipart/form-data
  3. 您可以使用application/json 发送 JSON
  4. text/plain发送原始文本

见:How are parameters sent in an HTTP POST request?

图像:图像或图形数据,包括位图和矢量静止图像以及静止图像格式的动画版本,例如动画 GIF 或 APNG。常见的例子有 image/jpeg、image/png 和 image/svg+xml。

你可以这样取数据(我想,这只适用于多个文件multipart/form-data):

face=request.files['face'].read()

也许其他人是:

request.form['face']
request.data['face']
request.get_data['face']
request.get_json['face']

以下是从 POST 请求中接收数据的正确且不同的方式:Get the data received in a Flask request

查看更多:Flask HTTP methods, handle GET & POST requests

【讨论】:

  • 如果我将 requests.get 更改为 requests.post,它会解决我的问题吗?
  • 无论如何我都会尝试
  • 那行不通。我也得到了 PaddingError。我应该使用 requests.post(url, params={'face':get_img_content()}) 而不是 requests.post('127:0:0:1:5000/?face={get_img_content()}') 吗?
  • 如果你把数据放在url里面,那么你就是在使用GET请求
猜你喜欢
  • 1970-01-01
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 2012-10-05
  • 2017-07-24
  • 1970-01-01
  • 2017-01-09
  • 2022-11-30
相关资源
最近更新 更多