diff --git a/components/FileListing.tsx b/components/FileListing.tsx index 08b741a..bcbb9d3 100644 --- a/components/FileListing.tsx +++ b/components/FileListing.tsx @@ -12,7 +12,7 @@ import dynamic from 'next/dynamic' import { getExtension, getFileIcon, hasKey } from '../utils/getFileIcon' import { extensions, preview } from '../utils/getPreviewType' -import { getBaseUrl, useProtectedSWRInfinite } from '../utils/tools' +import { getBaseUrl, saveFiles, useProtectedSWRInfinite } from '../utils/tools' import { VideoPreview } from './previews/VideoPreview' import { AudioPreview } from './previews/AudioPreview' @@ -235,6 +235,15 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) = } } + // Selected file download + const handleDownloadSelected = () => { + const folderName = path.substr(path.lastIndexOf('/') + 1) + const folder = folderName ? folderName : undefined + const files = children.filter((c: any) => selected[c.id]) + .map((c: any) => ({ name: c.name, url: c['@microsoft.graph.downloadUrl'] })) + saveFiles(files, folder) + } + return (
@@ -250,12 +259,15 @@ const FileListing: FunctionComponent<{ query?: ParsedUrlQuery }> = ({ query }) = indeterminate={true} title={"Select files"} /> - - - + {totalSelected ? ( + + + + ) : ''}
diff --git a/package-lock.json b/package-lock.json index 14744c7..7da8e35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "axios": "^0.21.1", "crypto-js": "^4.1.1", "emoji-regex": "^9.2.2", + "jszip": "^3.7.1", "next": "^11.1.0", "preview-office-docs": "^1.0.2", "prismjs": "^1.23.0", diff --git a/package.json b/package.json index ca4de1c..4fbfae6 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "axios": "^0.21.1", "crypto-js": "^4.1.1", "emoji-regex": "^9.2.2", + "jszip": "^3.7.1", "next": "^11.1.0", "preview-office-docs": "^1.0.2", "prismjs": "^1.23.0", diff --git a/utils/tools.ts b/utils/tools.ts index 904e263..c9dd3e1 100644 --- a/utils/tools.ts +++ b/utils/tools.ts @@ -1,6 +1,7 @@ import axios from 'axios' import sha256 from 'crypto-js/sha256' import useSWR, { cache, Key, useSWRInfinite } from 'swr' +import JSZip from 'jszip' import siteConfig from '../config/site.json' @@ -123,3 +124,27 @@ export const matchProtectedRoute = (route: string) => { } return authTokenPath } + +/** + * Download multiple files after compressing them into a zip + * @param files Files to be downloaded + * @param folder Optional folder name to hold files, otherwise flatten files in the zip + */ +export const saveFiles = (files: { name: string, url: string }[], folder?: string) => { + const zip = new JSZip() + const dir = folder ? zip.folder(folder)! : zip + files.forEach(({ name, url }) => { + dir.file(name, fetch(url).then(r => r.blob())) + }) + dir.generateAsync({ type: 'blob' }).then(b => { + const el = document.createElement('a') + el.style.display = 'none' + document.body.appendChild(el) + const bUrl = window.URL.createObjectURL(b) + el.href = bUrl + el.download = folder ? folder + '.zip' : 'download.zip' + el.click() + window.URL.revokeObjectURL(bUrl) + el.remove() + }) +}