print with a random code

This commit is contained in:
Davide Alberani 2019-08-15 10:41:24 +02:00
parent 2e395edfd1
commit ad2051e0e0
4 changed files with 79 additions and 18 deletions

View file

@ -21,6 +21,8 @@ Now you can **point your browser to [http://localhost:7777/](http://localhost:77
You can also **run the server in https**, putting in the *ssl* directory two files named *httprint_key.pem* and *httprint_cert.pem* You can also **run the server in https**, putting in the *ssl* directory two files named *httprint_key.pem* and *httprint_cert.pem*
By default the **--print-with-code** argument is true, and the uploaded files are just scheduled for priting. To actually print them, you should supply the generated code, for example: `curl -X POST http://localhost:7777/api/print/1234`
# License and copyright # License and copyright

View file

@ -12,8 +12,10 @@ function uploadFile() {
if (reply && !reply.error) { if (reply && !reply.error) {
iziToast.success({ iziToast.success({
title: "DONE!", title: "DONE!",
message: "file sent to printer", message: reply.message,
position: 'topCenter', position: 'topCenter',
timeout: false,
closeOnEscape: true,
layout: 2 layout: 2
}); });
} else { } else {

View file

@ -16,9 +16,11 @@ limitations under the License.
""" """
import os import os
import re
import time import time
import glob
import random import random
import asyncio import shutil
import logging import logging
import subprocess import subprocess
import multiprocessing as mp import multiprocessing as mp
@ -32,10 +34,12 @@ from tornado import gen, escape
API_VERSION = '1.0' API_VERSION = '1.0'
UPLOAD_PATH = 'uploads' QUEUE_DIR = 'queue'
ARCHIVE = True
ARCHIVE_DIR = 'archive'
PRINT_CMD = ['lp'] PRINT_CMD = ['lp']
PROCESS_TIMEOUT = 60 CODE_DIGITS = 4
ENCODING = 'utf-8' PRINT_WITH_CODE = True
logger = logging.getLogger() logger = logging.getLogger()
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO)
@ -118,8 +122,51 @@ class BaseHandler(tornado.web.RequestHandler):
p = mp.Process(target=self._run, args=(cmd,)) p = mp.Process(target=self._run, args=(cmd,))
p.start() p.start()
def print_file(self, fname):
cmd = PRINT_CMD + [fname]
self.run_subprocess(cmd)
if self.cfg.archive:
if not os.path.isdir(self.cfg.archive_dir):
os.makedirs(self.cfg.archive_dir)
shutil.move(fname, self.cfg.archive_dir)
class PrintHandler(BaseHandler):
"""File print handler."""
@gen.coroutine
def post(self, code=None):
if not code:
self.build_error("empty code")
return
files = glob.glob(self.cfg.queue_dir + '/%s-*' % code)
if not files:
self.build_error("no matching files")
return
self.print_file(files[0])
self.build_success("file sent to printer")
class UploadHandler(BaseHandler): class UploadHandler(BaseHandler):
"""Reset schedules handler.""" """File upload handler."""
def generateCode(self):
filler = '%0' + str(self.cfg.code_digits) + 'd'
existing = set()
re_code = re.compile('(\d{' + str(self.cfg.code_digits) + '})-.*')
for fname in glob.glob(self.cfg.queue_dir + '/*'):
fname = os.path.basename(fname)
match = re_code.match(fname)
if not match:
continue
fcode = match.group(1)
existing.add(fcode)
code = None
for i in range(10**self.cfg.code_digits):
intCode = random.randint(0, (10**self.cfg.code_digits)-1)
code = filler % intCode
if code not in existing:
break
return code
@gen.coroutine @gen.coroutine
def post(self): def post(self):
if not self.request.files.get('file'): if not self.request.files.get('file'):
@ -132,13 +179,12 @@ class UploadHandler(BaseHandler):
extension = os.path.splitext(webFname)[1] extension = os.path.splitext(webFname)[1]
except Exception: except Exception:
pass pass
if not os.path.isdir(UPLOAD_PATH): if not os.path.isdir(self.cfg.queue_dir):
os.makedirs(UPLOAD_PATH) os.makedirs(self.cfg.queue_dir)
fname = '%s-%s%s' % ( now = time.strftime('%Y%m%d%H%M%S')
time.strftime('%Y%m%d%H%M%S'), code = self.generateCode()
'%04d' % random.randint(0, 9999), fname = '%s-%s%s' % (code, now, extension)
extension) pname = os.path.join(self.cfg.queue_dir, fname)
pname = os.path.join(UPLOAD_PATH, fname)
try: try:
with open(pname, 'wb') as fd: with open(pname, 'wb') as fd:
fd.write(fileinfo['body']) fd.write(fileinfo['body'])
@ -147,11 +193,14 @@ class UploadHandler(BaseHandler):
return return
try: try:
with open(pname + '.info', 'w') as fd: with open(pname + '.info', 'w') as fd:
fd.write('originale file name: %s\n' % webFname) fd.write('original file name: %s\n' % webFname)
fd.write('uploaded on: %s\n' % now)
except Exception: except Exception:
pass pass
cmd = PRINT_CMD + [pname] if self.cfg.print_with_code:
self.run_subprocess(cmd) self.build_success("go to the printer and enter this code: %s" % code)
else:
self.print_file(pname)
self.build_success("file sent to printer") self.build_success("file sent to printer")
@ -175,6 +224,11 @@ def serve():
help='specify the SSL certificate to use for secure connections') help='specify the SSL certificate to use for secure connections')
define('ssl_key', default=os.path.join(os.path.dirname(__file__), 'ssl', 'httprint_key.pem'), define('ssl_key', default=os.path.join(os.path.dirname(__file__), 'ssl', 'httprint_key.pem'),
help='specify the SSL private key to use for secure connections') help='specify the SSL private key to use for secure connections')
define('code-digits', default=CODE_DIGITS, help='number of digits of the code', type=int)
define('queue-dir', default=QUEUE_DIR, help='directory to store files before they are printed', type=str)
define('archive', default=True, help='archive printed files', type=bool)
define('archive-dir', default=ARCHIVE_DIR, help='directory to archive printed files', type=str)
define('print-with-code', default=True, help='a code must be entered for printing', type=bool)
define('debug', default=False, help='run in debug mode', type=bool) define('debug', default=False, help='run in debug mode', type=bool)
tornado.options.parse_command_line() tornado.options.parse_command_line()
@ -185,12 +239,15 @@ def serve():
if os.path.isfile(options.ssl_key) and os.path.isfile(options.ssl_cert): if os.path.isfile(options.ssl_key) and os.path.isfile(options.ssl_cert):
ssl_options = dict(certfile=options.ssl_cert, keyfile=options.ssl_key) ssl_options = dict(certfile=options.ssl_cert, keyfile=options.ssl_key)
init_params = dict(listen_port=options.port, logger=logger, ssl_options=ssl_options) init_params = dict(listen_port=options.port, logger=logger, ssl_options=ssl_options, cfg=options)
_upload_path = r'upload/?' _upload_path = r'upload/?'
_print_path = r'print/(?P<code>\d+)'
application = tornado.web.Application([ application = tornado.web.Application([
(r'/api/%s' % _upload_path, UploadHandler, init_params), (r'/api/%s' % _upload_path, UploadHandler, init_params),
(r'/api/v%s/%s' % (API_VERSION, _upload_path), UploadHandler, init_params), (r'/api/v%s/%s' % (API_VERSION, _upload_path), UploadHandler, init_params),
(r'/api/%s' % _print_path, PrintHandler, init_params),
(r'/api/v%s/%s' % (API_VERSION, _print_path), PrintHandler, init_params),
(r'/?(.*)', TemplateHandler, init_params), (r'/?(.*)', TemplateHandler, init_params),
], ],
static_path=os.path.join(os.path.dirname(__file__), 'dist/static'), static_path=os.path.join(os.path.dirname(__file__), 'dist/static'),