First thumbnail attempt
This commit is contained in:
parent
b6ddbfb92b
commit
1034df02f2
|
|
@ -1,4 +1,5 @@
|
|||
.idea
|
||||
public/.thumbnail
|
||||
|
||||
node_modules
|
||||
build
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"start-client": "react-scripts start",
|
||||
"build-client": "react-scripts build",
|
||||
"build-client": "react-scripts build && npm run set-environment",
|
||||
"test-client": "react-scripts test",
|
||||
"eject-client": "react-scripts eject",
|
||||
"set-environment": "npx react-inject-env set",
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@
|
|||
"ts": "never",
|
||||
"tsx": "never"
|
||||
}
|
||||
]
|
||||
],
|
||||
"import/prefer-default-export": "off"
|
||||
},
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -17,6 +17,7 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@types/sharp": "^0.30.1",
|
||||
"@types/express": "^4.17.13",
|
||||
"@typescript-eslint/eslint-plugin": "^5.18.0",
|
||||
"@typescript-eslint/parser": "^5.18.0",
|
||||
|
|
@ -33,6 +34,7 @@
|
|||
"express": "^4.17.3",
|
||||
"image-size": "^1.0.1",
|
||||
"nodemon": "^2.0.15",
|
||||
"sharp": "^0.30.3",
|
||||
"ts-node": "^10.7.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,12 @@ import * as fs from "fs";
|
|||
import * as path from "path";
|
||||
import sizeOf from "image-size";
|
||||
import { a, Folder, Folders, Image } from "./models";
|
||||
import { publicPath, walk } from "./fsExtension";
|
||||
import { walk } from "./fsExtension";
|
||||
import {
|
||||
createThumbnailAsyncForImage,
|
||||
initThumbnailsAsync,
|
||||
} from "./thumbnails";
|
||||
import { publicPath, thumbnailPath, thumbnailPublicPath } from "./paths";
|
||||
|
||||
const app = express();
|
||||
|
||||
|
|
@ -19,15 +24,23 @@ app.get("/api(/*)?", (req, res) => {
|
|||
const dirents = fs.readdirSync(publicPath + requestedPath, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
const thumbnails = fs.readdirSync(thumbnailPublicPath + requestedPath);
|
||||
|
||||
const normalizedPath = requestedPath === "/" ? "" : requestedPath;
|
||||
const images: Image[] = dirents
|
||||
.filter((f) => f.isFile())
|
||||
.map((f) => {
|
||||
const thumbnailExists: boolean = thumbnails.includes(f.name);
|
||||
if (!thumbnailExists) {
|
||||
createThumbnailAsyncForImage(`${requestedPath}/${f.name}`);
|
||||
}
|
||||
|
||||
const dimensions = sizeOf(`${publicPath}${requestedPath}/${f.name}`);
|
||||
const widthAndHeightSwap = dimensions.orientation > 4; // see https://exiftool.org/TagNames/EXIF.html
|
||||
return {
|
||||
src: `/images${normalizedPath}/${f.name}`,
|
||||
src: thumbnailExists
|
||||
? `/images${thumbnailPath}${normalizedPath}/${f.name}`
|
||||
: `/images${normalizedPath}/${f.name}`,
|
||||
width: widthAndHeightSwap ? dimensions.height : dimensions.width,
|
||||
height: widthAndHeightSwap ? dimensions.width : dimensions.height,
|
||||
};
|
||||
|
|
@ -37,7 +50,7 @@ app.get("/api(/*)?", (req, res) => {
|
|||
});
|
||||
|
||||
app.get("/directories", (req, res) => {
|
||||
res.json(a<Folders>(walk("/")));
|
||||
res.json(a<Folders>(walk("")));
|
||||
});
|
||||
|
||||
// All other GET requests not handled before will return our React app
|
||||
|
|
@ -48,6 +61,10 @@ app.get("*", (req, res) => {
|
|||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
// eslint-disable-next-line no-console
|
||||
/* eslint-disable no-console */
|
||||
console.log(`Start processing thumbnails async`);
|
||||
initThumbnailsAsync("");
|
||||
|
||||
return console.log(`Express is listening at http://localhost:${PORT}`);
|
||||
/* eslint-enable no-console */
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import fs from "fs";
|
||||
import * as path from "path";
|
||||
import { Folders } from "./models";
|
||||
|
||||
export const publicPath = "../public";
|
||||
import { publicPath, thumbnailPath } from "./paths";
|
||||
|
||||
export const walk = (dirPath: string): Folders => {
|
||||
const dirEnts = fs.readdirSync(publicPath + dirPath, { withFileTypes: true });
|
||||
const dirEnts = fs.readdirSync(`${publicPath}/${dirPath}`, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
|
||||
return {
|
||||
name: path.basename(dirPath) || "Home",
|
||||
|
|
@ -13,6 +14,7 @@ export const walk = (dirPath: string): Folders => {
|
|||
numberOfFiles: dirEnts.filter((f) => f.isFile()).length,
|
||||
children: dirEnts
|
||||
.filter((d) => d.isDirectory())
|
||||
.filter((d) => !d.name.includes(thumbnailPath.substring(1)))
|
||||
.map((d) => walk(path.posix.join(dirPath, d.name))),
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export const publicPath = "../public";
|
||||
export const thumbnailPath = `/.thumbnail`;
|
||||
export const thumbnailPublicPath = `${publicPath}${thumbnailPath}`;
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import sharp from "sharp";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { publicPath, thumbnailPath, thumbnailPublicPath } from "./paths";
|
||||
|
||||
const percentage = 25;
|
||||
const minimumPixelForThumbnail = 1000;
|
||||
|
||||
export const createThumbnailAsyncForImage = (image: string) => {
|
||||
sharp(`${publicPath}${image}`)
|
||||
.metadata()
|
||||
.then((info) => {
|
||||
let width = Math.round((info.width * percentage) / 100);
|
||||
let height = Math.round((info.height * percentage) / 100);
|
||||
// no thumbnail if both sides are smaller than minimumPixelForThumbnail
|
||||
if (
|
||||
info.width <= minimumPixelForThumbnail &&
|
||||
info.height <= minimumPixelForThumbnail
|
||||
) {
|
||||
width = info.width;
|
||||
height = info.height;
|
||||
}
|
||||
|
||||
fs.mkdir(
|
||||
thumbnailPublicPath + path.dirname(image),
|
||||
{ recursive: true },
|
||||
() => {
|
||||
sharp(`${publicPath}${image}`)
|
||||
.resize(width, height)
|
||||
.toFile(`${thumbnailPublicPath}${image}`);
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export const initThumbnailsAsync = (dirPath: string) => {
|
||||
if (dirPath.includes(thumbnailPath)) {
|
||||
return;
|
||||
}
|
||||
const dirEnts = fs.readdirSync(publicPath + dirPath, { withFileTypes: true });
|
||||
|
||||
dirEnts
|
||||
.filter((f) => f.isFile())
|
||||
.map((f) => createThumbnailAsyncForImage(`${dirPath}/${f.name}`));
|
||||
dirEnts
|
||||
.filter((f) => f.isDirectory())
|
||||
.forEach((d) => initThumbnailsAsync(`${dirPath}/${d.name}`));
|
||||
};
|
||||
Loading…
Reference in New Issue