#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
@Time: 2022/5/16 16:19
@Author: SPZ
@File: app
@Project: OcrOnlineService
@Software: PyCharm
"""
import json
import os
from io import BytesIO
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.responses import StreamingResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
import hydra
from config.config_model import config
import aiohttp
from starlette.requests import Request
from enum import Enum
import datetime
import time
from datetime import datetime as dt
count = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
         0, 0, 0, 0, 0, 0, 0, 0, 0]  # 初始访问次数
ip_list = []
d = {}

app = FastAPI()
allowed_origins = ['*']

app.add_middleware(
    CORSMiddleware,
    allow_origins=allowed_origins,
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
    expose_headers=['*']
)


class ResponseType(Enum):
    image = 'image'
    json = 'json'


@app.post('/OcrTest')  # 本地接口
async def ocr_test(request: Request, file: UploadFile = File(...), authorization_code: str = Form(...),
                   response_type: ResponseType = Form(ResponseType.image)):
    if authorization_code != config['authorization_code']:
        return JSONResponse({'message': '授权码错误'}, status_code=401)

    global count
    request_date = dt.today().date()
    print(request_date)
    now = dt.now()
    print(now)
    print(config.last_request_date)
    if request_date != config.last_request_date:  #当最后一次请求的日期与当日日期不同,则重置参数
        for idx in range(len(count)):
            count[idx] = 0
        config.set_date(request_date)
    limit_time = config['time_limit']
    client_host_ip = request.client.host
    flag = 0
    pos = 0
    for i in ip_list:
        if i == client_host_ip:  # 找到相等就退出
            flag = 1
            print("ip出现在列表中的位置:", pos)
            break
        else:
            pos += 1

    if flag == 0:  # 第一次出现的ip
        ip_list.append(client_host_ip)
        pos = len(ip_list) - 1
        d[client_host_ip] = count[pos]
    else:  # 之前出现过的ip
        d[client_host_ip] = count[pos]

    if d[client_host_ip] < limit_time:
        data = await file.read()  # 先读取本地上传到本地接口的数据
        data1 = await interface(data, config, response_type)  # 通过本地端口将数据读取到远端端口从而进行相关ocr函数处理
        count[pos] += 1
        print("今日已试验{}次".format(count[pos]))
        daily_charges = limit_time - count[pos]
        header = {'daily_charges': str(daily_charges)}  #headers改变了
        if response_type == ResponseType.image:
            return StreamingResponse(BytesIO(data1), media_type='image/png', headers=header)
        else:
            return JSONResponse(data1, headers=header)
    elif d[client_host_ip] >= limit_time:
        daily_charges = limit_time - count[pos]
        header = {'daily_charges': str(daily_charges)}
        print("今日已试验{}次".format(count[pos]))
        return JSONResponse({'message': "已达到今日试验次数上限!请明日再使用!"}, status_code=503, headers=header)

# 上传文件
async def interface(file_data: bytes, config, response_type):
    url = config.ocr_url
    print("url:", url)
    multipart_writer = aiohttp.MultipartWriter('mixed')
    # add parameters
    # 普通参数
    data = {'display': response_type.value}
    for k, v in data.items():
        multipart_writer.append(v).set_content_disposition('form-data', name=k)

    # 添加上传文件的参数
    # add files data
    files = {'files': BytesIO(file_data)}
    for k, v in files.items():
        # print('k,v:',k,v)
        multipart_writer.append(BytesIO(file_data), {'Content-Type': 'image/png'}).set_content_disposition(
            'form-data',
            name=k,
            filename='0.png'
        )

    # 请求远端端口并读取数据
    async with aiohttp.request('POST', url=url, data=multipart_writer, headers={
        'Content-Type': 'multipart/form-data; boundary=' + multipart_writer.boundary}) as r:
        print(r.status)  # 之前访问为422,是因为,添加上传文件的参数名不正确
        if response_type == ResponseType.image:
            result = await r.content.read()
        else:
            result = await r.json()
    return result

1.总结思路:主要实现的功能就是将自己这台电脑作为访问接口,用户通过访问我这个主机的接口来实现另一端实际接口的访问,即我这个主机接口起到的是中转的作用。其次,第二个功能就是,由于要实现服务器资源的充分利用,不能让用户恶意访问,所以要限制用户每日访问的次数。

这个接口的作用:实现上传一张png图片后,用ocr算法进行处理,返回ocr处理后的图/json信息。

2.其中重要的实现点就是要理解,怎么实现转让接口的,怎么使访问这个接口而实现到另一个接口的功能的?

 

 

使用协程等待,用户上传的文件   data = await 函数(xxxx,xxxxx,xx)

 config.cor_url即是真正需要访问的接口url

 这样就实现了中转!!!这点为思路最重要的点!(因为这个url才是真正上传和处理的接口位置,并且会进行请求远端的端口,返回读取到的数据)

 3.怎么实现的对应接口中的参数呢?

其实并没有真正的实现点击上传文件,在对应的远端就执行了上传功能,而是在等着中转接口所有的操作都做完了,点击execute才真正执行到远端。所以不要在这一点上混淆了!并没有实现功能点击一 一对应,而是在最后点击execute以后,才执行远端接口的。

4.怎么实现设置fastapi界面当中的参数的呢?

在装饰函数定义参数当中实现的!

 

 5.远端如何实现上传文件呢?

1.添加普通参数的方法:

 2.添加文件参数的方法(最初不知道添加这两种参数是有区别的,就直接将文件参数当作普通参数添加的,发现一直都没有返回图片字节流)

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐