最近在抖音上看到一个卖孟婆汤的,居然卖得如火如荼,恭喜你成了那条街上最靓的女,这孟婆汤是啥味?看来地摊经济还是需要卖好的创意,不知道能火多久(羡慕嫉妒中……),哎,自己没啥好创意,做不了街上最靓的仔,那就争取做最靓的猿吧!
接着上篇来讲,上篇我们实现了对PDF的图片提取,那这篇我们就使用websocket来实现提取的进度的实时展示吧,那如何实现websocket的服务呢,在Sanic框架中自带的方法,来,小二上代码:
@app.websocket('/feed')
async def feed(request, ws):
while True:
data = 'hello!'
print('Sending: ' + data)
await ws.send(data)
data = await ws.recv()
print('Received: ' + data)
这是官方给出的例子,非常简单,在前端可以利用html5的websocket配合使用,具体的实现大家可以自己操作下。
在我们创建的网站里我们只要实现的逻辑就是提取成功一页PDF就将提取的文件路径发送给前端,前端接收到信息就及时展示出来,在这个过程中我遇到了一个问题,就是我执行逻辑方法的时候是在这个服务的外部,我怎么在外部使用ws.send的方法来发送信息呢?我的想法就是在请求websocket服务的时候同时传递一个用户的链接的唯一标识,保存到全局,当任务执行结束后,自动删除此用户标识以释放资源,来,首先我们定义个全局变量:
app.ws = {}
websocket服务代码:
#PDF执行进度websocket
@app.websocket('/extract/')
async def extract(request, ws, id):
app.ws[id] = ws
while True:
result=await ws.recv()
print("result",result)
你也可以这样写:
async def extract(request, ws, id):
app.ws[id] = ws
while True:
result=await ws.recv()
print("result",result)
app.add_websocket_route(extract, '/extract/')
为了上下文请求写法的格式统一,我还是用第一种方式,接着我们来实现上传文件及提取PDF的方法:
#上传文件接口
@app.route('/upload',methods=["POST"])
async def upload(request):
args = request.args if request.method == 'GET' else request.form
uid = args.get('uid', 0)
file = request.files.get('file')
#放入后台执行
app.add_task(extract_pdf(uid,file.body))
msg={"code":200,"msg":"开始执行提取PDF"}
return json(msg)
#执行方法
async def extract_pdf(id,stream):
#定义Pdf类
p = Pdf()
doc = fitz.open('type',stream)
for i in range(doc.pageCount):
#await asyncio.sleep(0.1)
filename=await asyncio.ensure_future(p.pdf2pic(doc,i))
await app.ws[id].send(filename)
doc.close()
#执行完毕删除掉webscoket
del app.ws[id]
print("已成功删除了websocket:",id)
在异步框架中记得在方法前加上async,在执行方法中使用了asyncio.ensure_future就是将PDF的处理方法放到想协程里执行,这样就不会阻塞主线程,处理PDF的过程上篇的PDF的方法要稍做调整,因为这里要异步调用,而且我们直接将文件流传递到PDF提取的方法中,我们这样修改下:
async def pdf2pic(self,doc,pageCount):
将这2行去掉:
#加载读取pdf文件
doc = fitz.open(filename)
#循环提取pdf页面
for i in range(doc.pageCount):
前端页面的代码:
Title
细心的同学可以看到这里面有个msg.uid,这就是为了做唯一标识在请求首页的时候就返回的一个标识码:
#首页
@app.route('/')
async def index(request):
msg={"name":"李大厨","sex":"男","uid":uuid.uuid4()}
return jinja.render('index.html',request, msg=msg)
这里使用了uuid来生成,嗯,跟好节奏,来我们运行看一下结果:
这样我们就实现了在线PDF的图片提取部分,通过上面你的例子其实有很多发散的思考,比如我们还是做个进度条来展示实时进度什么的,还可以显示文件总数,正在处理,已处理个数等等,有兴趣的大家可以研究下。
好了,实现在线PDF的提取及压缩的提取部分就到这里了。
如果有需要的源代码的同学,请关注公众号回复:pdf
江湖故人,相逢何必曾相识!咱们下篇见!
关注公众号,超越平凡才能成就自我