forked from devmanorg/async-download-service
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.py
85 lines (74 loc) · 2.89 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import asyncio
from aiohttp import web
import datetime
import aiofiles
import os
import logging
import argparse
from functools import partial
CHUNK_SIZE = 1000
async def archivate(request, photos_folder, download_delay):
response = web.StreamResponse()
response.headers['Content-Type'] = 'application/zip'
response.headers['Content-Disposition'] = 'attachment'
# Отправляет клиенту HTTP заголовки
await response.prepare(request)
archive_hash = request.match_info['archive_hash']
archive_path = os.path.join(photos_folder, archive_hash)
if not os.path.isdir(archive_path):
raise web.HTTPNotFound(text='Archive not found')
archiving_proc = await asyncio.create_subprocess_exec('zip', '-r', '-', archive_path,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE)
try:
while True:
logging.debug('Sending archive chunk')
archive_chunk = await archiving_proc.stdout.read(CHUNK_SIZE)
if not archive_chunk:
break
await response.write(archive_chunk)
await asyncio.sleep(download_delay)
except asyncio.CancelledError:
logging.debug('Download was interrupted')
raise
finally:
response.force_close()
if archiving_proc.returncode is None:
archiving_proc.kill()
return response
async def handle_index_page(request):
async with aiofiles.open('index.html', mode='r') as index_file:
index_contents = await index_file.read()
return web.Response(text=index_contents, content_type='text/html')
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Photo downloading microservice')
parser.add_argument('--logging',
default='on',
type=str,
help='Shows the debug messages')
parser.add_argument('--photos_folder',
default='test_photos',
type=str,
help='Path to the folder with photos')
parser.add_argument('--delay',
default=0,
type=int,
help='Number of seconds to delay the downloading of each archive chunk')
args = parser.parse_args()
logging.basicConfig(level=logging.DEBUG)
if args.logging != 'on':
logging.basicConfig(level=logging.CRITICAL)
download_delay = args.delay
photos_folder = args.photos_folder
archivate_partial = partial(
archivate,
photos_folder=photos_folder,
download_delay=download_delay
)
app = web.Application()
app.add_routes([
web.get('/', handle_index_page),
web.get('/archive/{archive_hash}/', archivate_partial)
])
web.run_app(app)