119 lines
3.5 KiB
JavaScript
119 lines
3.5 KiB
JavaScript
const fs = require("fs");
|
|
const path = require("path");
|
|
const { ENOENT, ECONNRESET } = require("constants");
|
|
|
|
const Koa = require("koa");
|
|
const koaPug = require("koa-pug");
|
|
const koaRouter = require("koa-router");
|
|
|
|
const config = require("./config");
|
|
const util = require("../shared/util");
|
|
|
|
|
|
|
|
const SIZE_UNITS = [ "B", "KiB", "MiB", "GiB" ];
|
|
|
|
function addFileSizeUnit(size) {
|
|
let i = 0;
|
|
for (; size > 1024; size /= 1024) ++i;
|
|
return [i > 0 ? size.toFixed(2) : size, SIZE_UNITS[i]];
|
|
}
|
|
|
|
|
|
function buildCurrentPathLink(path) {
|
|
let currentPath = `<a href="/">root</a>`;
|
|
|
|
if (path.endsWith("/"))
|
|
path = path.slice(1, path.length-1);
|
|
|
|
const path_parts = path.split("/");
|
|
|
|
for (let i = 0; i < path_parts.length; ++i) {
|
|
let lnk = "";
|
|
|
|
for (let j = 0; j < i+1; ++j)
|
|
lnk += `/${path_parts[j]}`;
|
|
|
|
currentPath += `/<a href="${encodeURI(lnk)}/">${path_parts[i]}</a>`;
|
|
}
|
|
|
|
return currentPath;
|
|
}
|
|
|
|
function sortFuncByNameField(a, b) {
|
|
return (a.name > b.name) ? 1 : (a.name < b.name) ? -1 : 0;
|
|
}
|
|
|
|
async function getDirectoryList(dir_path, orig_url) {
|
|
let directories = [];
|
|
let files = [];
|
|
let total_files_size = 0;
|
|
let directory = await fs.promises.opendir(dir_path);
|
|
|
|
for await (const dirent of directory) {
|
|
const stat = await fs.promises.stat(path.join(dir_path, dirent.name));
|
|
const [s, u] = addFileSizeUnit(stat.size);
|
|
|
|
if (stat.isDirectory())
|
|
directories.push({
|
|
name: dirent.name,
|
|
link: `${encodeURIComponent(dirent.name)}/`,
|
|
datetime: stat.mtime,
|
|
size: "DIR" });
|
|
else {
|
|
total_files_size += stat.size;
|
|
files.push({
|
|
name: dirent.name,
|
|
link: `/files${orig_url}${encodeURIComponent(dirent.name)}`,
|
|
datetime: stat.mtime,
|
|
size: `${s} ${u}` });
|
|
}
|
|
}
|
|
|
|
directories.sort(sortFuncByNameField);
|
|
files.sort(sortFuncByNameField);
|
|
|
|
return [directories.concat(files), directories.length, files.length,
|
|
addFileSizeUnit(total_files_size).join(' ')];
|
|
}
|
|
|
|
function setRoutes() {
|
|
return koaRouter().get('/(.*)?', async ctx => {
|
|
const file_path = path.join(config.share_path, decodeURI(ctx.originalUrl));
|
|
|
|
let stat = await fs.promises.stat(file_path);
|
|
|
|
if (stat.isDirectory()) {
|
|
const [items, total_directories, total_files, total_files_size]
|
|
= await getDirectoryList(file_path, decodeURI(ctx.originalUrl));
|
|
|
|
await ctx.render('index', {
|
|
title: "/ Files",
|
|
description: "File share.",
|
|
clientTZ: util.getClientTimezone(ctx),
|
|
main_site: util.getServiceByHost(ctx.header.host),
|
|
current_path: buildCurrentPathLink(decodeURI(ctx.originalUrl)),
|
|
total_files: total_files,
|
|
total_files_size: total_files_size,
|
|
total_directories: total_directories,
|
|
items: items });
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
const app = new Koa();
|
|
const pug = new koaPug({
|
|
viewPath: path.join(__dirname, "views"),
|
|
locals: {
|
|
moment: (date, tz) => util.datetime(date, util.formats.file_date, tz), },
|
|
app: app
|
|
});
|
|
|
|
app.proxy = true;
|
|
app
|
|
.use(setRoutes().routes())
|
|
// .on("error", err => { if (!err.code == ECONNRESET || !err.code == ENOENT) console.log(err.code); })
|
|
.listen(config.port, config.host);
|
|
|
|
console.log("Arav's dwelling / Files is up."); |