UNPKG

http-up

Version:

Simple share folder via http with upload

321 lines (232 loc) 11.7 kB
import os from 'os'; import fs from 'fs'; import path from 'path'; import chalk from 'chalk'; import * as urlencode from 'urlencode'; import * as dateTime from 'node-datetime'; import mime from 'mime'; import shell from 'shelljs'; import { exec } from 'child_process'; import config from '../lib/config.js'; import * as util from '../lib/util.js'; import * as model from '../model/index.js'; export const api_thumb = (app, argv) => { app.get('/__thumb/*splat', async (req, res, next) => { let req_path = req.path; req_path = urlencode.decode(req_path); req_path = req_path.replace(/^\/__thumb/, ''); req_path = util.http_path_clear(req_path); //res.locals.argv = argv; res.locals.req_path = req_path; //let name = util.get_name(req_path); let ext = util.get_ext_norm(req_path); let is_preview_match = ext.match(/^(jpg|png|gif|txt|pdf|rtf|doc|docx|xls|xlsx|odt|ods)$/i); if (!is_preview_match) { res.status(500).json({ code: 500, msg: 'Thumbnails support only for image format and office files' }); return; } // --------------------------------------------------------------------- let full_filename_orig = path.join(argv.fold, req_path); if (!fs.existsSync(full_filename_orig)) { model.event_log.write(res, req, 404, 'thumb', full_filename_orig); res.status(404).json({ code: 404, msg: '404 Not found' }); return; } // --------------------------------------------------------------------- if (argv.usedb) { serve_with_db(req, res); } else { serve_without_db(req, res, ext); } }); }; // --------------------------------------------------------------------------------------------------------------------------------------------------------------- const serve_with_db = async (req, res) => { let argv = res.locals.argv; let req_path = res.locals.req_path; let full_filename_orig = path.join(argv.fold, req_path); //let ext = util.get_ext_norm(req_path); let db = model.connect(); // -------------------------------------------------------------------------------------------------- //model.file.md5_thumb_search( req, res, full_filename_orig ) // -------------------------------------------------------------------------------------------------- db.get(`select * from file where full_path =?`, [full_filename_orig], function (err, row) { if (err) { model.event_log.write(res, req, 500, 'thumb/serve_with_db', 'Internal Server ' + err); res.status(500).json({ code: 500, msg: 'Internal Server' }); return; } if (row && row.md5) { let md5_full_path = path.join(config.httpup_thumb, row.md5); fs.readFile(md5_full_path, (err, data) => { if (err) { model.event_log.write(res, req, 500, 'thumb/serve_with_db', 'Internal Server ' + err); res.status(500).json({ code: 500, msg: 'Internal Server' }); return; } model.event_log.print(res, req, 200, 'thumb/serve_with_db', 'SendData thumb DB ' + chalk.yellow(full_filename_orig)); const mime_type = mime.getType(row.ext); res.setHeader('content-type', mime_type); res.status(200).send(data); return; }); } else { let ext = util.get_ext_norm(full_filename_orig); serve_without_db(req, res, ext); return; } }); }; const serve_without_db = async (req, res, ext) => { // -------------------------------------------------------------------------------------------------- let is_preview_img = ext.match(/^(jpg|png|gif)$/i); if (is_preview_img) { preview_img(req, res); return; } let is_preview_doc = ext.match(/^(txt|pdf|rtf|doc|docx|xls|xlsx|odt|ods)$/i); if (is_preview_doc) { preview_doc(req, res); return; } }; // --------------------------------------------------------------------------------------------------------------------------------------------------------------- const preview_img = async (req, res) => { let argv = res.locals.argv; let req_path = res.locals.req_path; let full_filename_orig = path.join(argv.fold, req_path); let ext = util.get_ext_norm(req_path); // -------------------------------------------------------------------------------------------------- /* if (!fs.existsSync(full_filename_orig)) { model.event_log.write(res, req, 404, 'thumb/preview_img', full_filename_orig); res.status(404).json({ code: 404, msg: '404 Not found' }); return; } */ // -------------------------------------------------------------------------------------------------- let stats = fs.lstatSync(full_filename_orig); if (stats.size && stats.size <= 50 * 1024) { model.event_log.print(res, req, 200, 'thumb/preview_img', 'SendFile orig without resize ' + full_filename_orig + ' size is small'); const data = fs.readFileSync(full_filename_orig, { flag: 'r' }); res.setHeader('Content-Type', mime.getType(ext)); res.status(200).send(data); return; } // -------------------------------------------------------------------------------------------------- if (shell.exec('md5sum --help', { silent: true }).code !== 0) { model.event_log.write(res, req, 500, 'thumb/preview_img', 'Error: md5sum not found'); res.status(500).json({ code: 500, msg: 'md5sum not found' }); return; } if (shell.exec('convert --help', { silent: true }).code !== 0) { model.event_log.write(res, req, 500, 'thumb/preview_img', 'Error: convert not found'); res.status(500).json({ code: 500, msg: 'convert not found' }); return; } // -------------------------------------------------------------------------------------------------- exec(`md5sum "${full_filename_orig}"`, function (error, stdout, stderr) { let arr = stdout.split(/\s+/); let md5_file = arr[0]; if (md5_file.length == 0) { res.setHeader('Content-Type', 'application/json'); res.status(500).send(JSON.stringify({ code: 500, msg: 'error md5' })); return; } let stats = fs.lstatSync(full_filename_orig); let modtime = dateTime.create(stats.mtime); let modtime_human = modtime.format('Y-m-d H:M:S'); //model.file.add(full_filename_orig, name+'.'+ext, ext, 0, stats.size, modtime_human, md5_file); let md5_file_path = path.join(config.httpup_thumb, md5_file); if (fs.existsSync(md5_file_path)) { let file_stat = fs.lstatSync(md5_file_path); if (file_stat.size == 0) { fs.unlinkSync(md5_file_path); } } if (fs.existsSync(md5_file_path)) { const data = fs.readFileSync(md5_file_path, { flag: 'r' }); res.setHeader('Content-Type', mime.getType(ext)); res.status(200).send(data); model.event_log.print(res, req, 200, 'thumb/preview_img', 'sendFile', 'Thumbnail send ' + chalk.yellow(req_path)); //res.sendFile(md5_file_path); return; } exec(`convert "${full_filename_orig}" -resize 600x-1 -quality 75 ${path.join(config.httpup_thumb, md5_file)}`, function (error, stdout, stderr) {}); model.event_log.print(res, req, 200, 'thumb/preview_img', 'sendFile', 'Original send as thumbnail ' + chalk.yellow(req_path)); res.sendFile(full_filename_orig); //res.status(200).json({ code: 200, msg: 'Thumbnail is still not ready' }); return; }); }; // --------------------------------------------------------------------------------------------------------------------------------------------------------------- const preview_doc = async (req, res) => { let argv = res.locals.argv; let req_path = res.locals.req_path; let full_filename_orig = path.join(argv.fold, req_path); let ext = util.get_ext_norm(req_path); // -------------------------------------------------------------------------------------------------- if (!fs.existsSync(full_filename_orig)) { model.event_log.write(res, req, 404, 'thumb/preview_doc', full_filename_orig); res.status(404).json({ code: 404, msg: '404 Not found' }); return; } // -------------------------------------------------------------------------------------------------- if (shell.exec('md5sum --help', { silent: true }).code !== 0) { model.event_log.write(res, req, 500, 'thumb/preview_doc', 'Error: md5sum not found'); res.status(500).json({ code: 500, msg: 'md5sum not found' }); return; } if (shell.exec('libreoffice --help', { silent: true }).code !== 0) { model.event_log.write(res, req, 500, 'thumb/preview_doc', 'Error: libreoffice not found'); res.status(500).json({ code: 500, msg: 'libreoffice not found' }); return; } // -------------------------------------------------------------------------------------------------- exec(`md5sum "${full_filename_orig}"`, function (error, stdout, stderr) { let arr = stdout.split(/\s+/); let md5_file = arr[0]; if (md5_file.length == 0) { res.status(500).json({ code: 500, msg: 'error md5' }); return; } let stats = fs.lstatSync(full_filename_orig); let modtime = dateTime.create(stats.mtime); let modtime_human = modtime.format('Y-m-d H:M:S'); //model.file.add(full_filename_orig, name+'.'+ext, ext, 0, stats.size, modtime_human, md5_file); let md5_file_path = path.join(config.httpup_thumb, md5_file); if (fs.existsSync(md5_file_path)) { let file_stat = fs.lstatSync(md5_file_path); if (file_stat.size == 0) { fs.unlinkSync(md5_file_path); } } if (fs.existsSync(md5_file_path)) { const data = fs.readFileSync(md5_file_path, { flag: 'r' }); //res.setHeader('Content-Type', mime.getType(ext)); res.setHeader('Content-Type', 'image/png'); res.status(200).send(data); model.event_log.print(res, req, 200, 'thumb/preview_doc', 'sendFile', 'Thumbnail send ' + chalk.yellow(req_path)); //res.sendFile(md5_file_path); return; } exec( `libreoffice --headless --norestore --nologo --convert-to png --outdir "${config.httpup_thumb}" "${full_filename_orig}"`, function (error, stdout, stderr) { let name = util.get_name(req_path); let png_file = path.join(config.httpup_thumb, name + '.png'); if (fs.existsSync(png_file)) { fs.rename(png_file, md5_file_path, (err) => { if (err) { model.event_log.write(res, req, 500, 'thumb/preview_doc', 'fs.rename', 'err=', err); } }); } }, ); model.event_log.print(res, req, 200, 'thumb/preview_doc', 'Thumbnail still preparing ' + chalk.yellow(req_path)); res.status(200).json({ code: 200 }); return; }); }; // ---------------------------------------------------------------------------------------------------------------------------------------------------------------