Skip to content

Commit

Permalink
enhancement/Show_size_of_folder_and_files
Browse files Browse the repository at this point in the history
  • Loading branch information
sumitkumar931 committed Oct 27, 2024
1 parent f3f10a4 commit 26be0f8
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
30 changes: 30 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,38 @@ const getDownloadUrl = (path: string, forceDownload?: boolean) => `/api/download
const FileDownload = ({ url }: { url: string }) => <a style={{ textDecoration: 'none', marginLeft: 10, marginBottom: -5, color: colorLink }} href={url} title="Download file"><FaFileDownload size={22} /></a>;
const ZipDownload = ({ url, title = 'Download folder as ZIP', style }: { url: string, title?: string, style?: CSSProperties }) => <a style={{ textDecoration: 'none', color: colorLink2, verticalAlign: 'middle', ...style }} href={url} title={title}><FaFileArchive size={22} /></a>;

let sizeCounter: number = 0;

const sizeMeter: { [key: number]: string } = {
0: 'KB',
1: 'MB',
2: 'GB',
3: 'TB'
};

// Format the byte
const manageByte = (num: number): string | number => {
if (!num) return 0;
let res: number = num / 1024;

if (res > 1000) {
sizeCounter++;
return manageByte(res);
} else {
const value: number = sizeCounter;
sizeCounter = 0;
return res.toFixed(2) + sizeMeter[value];
}
}


const FileRow = ({ path, isDir, fileName, onCheckedChange, checked }: {
path: string,
isDir: boolean,
fileName: string,
onCheckedChange?: ChangeEventHandler<HTMLInputElement>,
checked?: boolean | undefined,
size?: number | undefined,
}) => {
const Icon = isDir ? FaFolder : FaFileAlt;

Expand All @@ -148,12 +174,14 @@ const FileRow = ({ path, isDir, fileName, onCheckedChange, checked }: {
<>
<Link to={{ pathname: '/', search: `?p=${encodeURIComponent(path)}` }} style={linkStyle}>{fileName} {fileName === '..' && <span style={{ color: 'rgba(0,0,0,0.3)' }}>(parent dir)</span>}</Link>
<div style={{ flexGrow: 1 }} />
<span style={{ marginRight: '.2em' }} > {size && manageByte(size)} </span>
<ZipDownload url={getDownloadUrl(path)} style={{ marginLeft: 10, marginBottom: -5 }} />
</>
) : (
<>
<a style={linkStyle} target="_blank" rel="noopener noreferrer" href={getDownloadUrl(path)}>{fileName}</a>
<div style={{ flexGrow: 1 }} />
<span style={{ marginRight: '.2em' }} > {size && manageByte(size)} </span>
{onCheckedChange != null && <input type="checkbox" className="inputcheckbox" checked={checked} onChange={onCheckedChange} />}
<FileDownload url={getDownloadUrl(path, true)} />
</>
Expand All @@ -179,6 +207,8 @@ const Browser = () => {
try {
const response = await axios.get('/api/browse', { params: { p: currentPath } });
setCurrentDirFiles(response.data);
let responseWithSize = await axios.get('/api/browse-withsize', { params: { p: currentPath } });
setCurrentDirFiles(responseWithSize.data);
} catch (err) {
console.error(err);
}
Expand Down
70 changes: 70 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,76 @@ export default ({ sharedPath: sharedPathIn, port, maxUploadSize, zipCompressionL
}));


async function getFolderSize(folderPath: string): Promise<number> {
let totalSize = 0;

async function calculateSize(dirPath: string): Promise<void> {
const files = await fs.readdir(dirPath); // Async readdir
for (const file of files) {
const filePath = join(dirPath, file);
const stats = await fs.stat(filePath); // Async stat

if (stats.isDirectory()) {
await calculateSize(filePath); // Recursively get size for subdirectories
} else {
totalSize += stats.size; // Add file size
}
}
}

await calculateSize(folderPath); // Start calculation from the root folder

return totalSize;
}

app.get('/api/browse-withsize', asyncHandler(async (req, res) => {
const browseRelPath = req.query['p'] || '/';
assert(typeof browseRelPath === 'string');
const browseAbsPath = await getFileAbsPath(browseRelPath);

let readdirEntries = await fs.readdir(browseAbsPath, { withFileTypes: true });
readdirEntries = readdirEntries.sort(({ name: a }, { name: b }) => new Intl.Collator(undefined, { numeric: true }).compare(a, b));

const entries = (await pMap(readdirEntries, async (entry) => {
try {
// TODO what if a file called ".."
const entryRelPath = join(browseRelPath, entry.name);
const entryAbsPath = join(browseAbsPath, entry.name);
const entryRealPath = await fs.realpath(entryAbsPath);

if (!entryRealPath.startsWith(sharedPath)) {
console.warn('Ignoring symlink pointing outside shared path', entryRealPath);
return [];
}

const stat = await fs.lstat(entryRealPath);
const isDir = stat.isDirectory();
const size = isDir ? await getFolderSize(entryRealPath) : stat.size

return [{
path: entryRelPath,
isDir,
fileName: entry.name,
size: size
}];
} catch (err) {
console.warn((err as Error).message);
// https://github.com/mifi/ezshare/issues/29
return [];
}
}, { concurrency: 10 })).flat();

res.send({
files: [
{ path: join(browseRelPath, '..'), fileName: '..', isDir: true },
...entries,
],
cwd: browseRelPath,
sharedPath,
});
}));


app.get('/api/zip-files', asyncHandler(async (req, res) => {
const zipFileName = `${new Date().toISOString().replace(/^(\d+-\d+-\d+)T(\d+):(\d+):(\d+).*$/, '$1 $2.$3.$3')}.zip`;
const { files: filesJson } = req.query;
Expand Down

0 comments on commit 26be0f8

Please sign in to comment.