try fflate
This commit is contained in:
parent
2b727e1755
commit
0f450e4189
5 changed files with 134 additions and 69 deletions
File diff suppressed because one or more lines are too long
104
content.js
104
content.js
|
|
@ -267,21 +267,66 @@ async function getArchiveViewerHtmlSource() {
|
|||
return response.text()
|
||||
}
|
||||
|
||||
// Bundle the viewer's JSZip runtime so the exported archive can be browsed offline.
|
||||
async function getArchiveViewerJsZipSource() {
|
||||
const candidates = [
|
||||
"lib/jszip.min.js"
|
||||
]
|
||||
// Bundle the viewer's fflate runtime so the exported archive can be browsed offline.
|
||||
async function getArchiveViewerFflateSource() {
|
||||
const response = await fetch(chrome.runtime.getURL("lib/fflate.min.js"))
|
||||
|
||||
for (const candidate of candidates) {
|
||||
const response = await fetch(chrome.runtime.getURL(candidate))
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to load archive viewer dependency")
|
||||
}
|
||||
|
||||
if (response.ok) {
|
||||
return response.text()
|
||||
}
|
||||
|
||||
function getFflate() {
|
||||
if (typeof fflate === "undefined") {
|
||||
throw new Error("fflate is not available")
|
||||
}
|
||||
|
||||
throw new Error("Failed to load archive viewer dependency")
|
||||
return fflate
|
||||
}
|
||||
|
||||
async function createZipBlob(entries, onProgress = () => { }) {
|
||||
const { strToU8, zip } = getFflate()
|
||||
const archiveEntries = {}
|
||||
let processedEntries = 0
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.data instanceof Blob) {
|
||||
archiveEntries[entry.path] = new Uint8Array(await entry.data.arrayBuffer())
|
||||
} else if (entry.data instanceof Uint8Array) {
|
||||
archiveEntries[entry.path] = entry.data
|
||||
} else {
|
||||
archiveEntries[entry.path] = strToU8(String(entry.data ?? ""))
|
||||
}
|
||||
|
||||
entry.data = null
|
||||
processedEntries += 1
|
||||
onProgress({
|
||||
phase: "preparing",
|
||||
processedEntries,
|
||||
totalEntries: entries.length
|
||||
})
|
||||
}
|
||||
|
||||
onProgress({
|
||||
phase: "generating",
|
||||
processedEntries,
|
||||
totalEntries: entries.length
|
||||
})
|
||||
|
||||
const archiveBytes = await new Promise((resolve, reject) => {
|
||||
zip(archiveEntries, { level: 0, consume: true }, (error, data) => {
|
||||
if (error != null) {
|
||||
reject(error)
|
||||
return
|
||||
}
|
||||
|
||||
resolve(data)
|
||||
})
|
||||
})
|
||||
|
||||
return new Blob([archiveBytes], { type: "application/zip" })
|
||||
}
|
||||
|
||||
function downloadBlob(blob, fileName) {
|
||||
|
|
@ -470,7 +515,7 @@ function rip(event) {
|
|||
|
||||
console.log("Preparing zip archive...")
|
||||
progressDialog.setStatus("Preparing zip archive...")
|
||||
const zip = new JSZip()
|
||||
const archiveEntries = []
|
||||
const successfulApplicants = []
|
||||
|
||||
applicantDetailsResults.forEach((result) => {
|
||||
|
|
@ -479,30 +524,53 @@ function rip(event) {
|
|||
}
|
||||
|
||||
const applicantDetails = result.value
|
||||
const dirName = getApplicantDirectoryName(applicantDetails)
|
||||
const applicantDir = zip.folder(`${APPLICATIONS_DIRECTORY}/${dirName}`)
|
||||
const archiveFiles = getApplicantArchiveFiles(applicantDetails)
|
||||
|
||||
successfulApplicants.push(applicantDetails)
|
||||
|
||||
archiveFiles.forEach((archiveFile, index) => {
|
||||
const afile = applicantDetails.application_files[index]
|
||||
applicantDir.file(archiveFile.fileName, afile.blob)
|
||||
archiveEntries.push({
|
||||
path: archiveFile.relativePath,
|
||||
data: afile.blob
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const [viewerHtmlSource, viewerFflateSource] = await Promise.all([
|
||||
getArchiveViewerHtmlSource(),
|
||||
getArchiveViewerFflateSource()
|
||||
])
|
||||
|
||||
console.log("Creating applicants.csv")
|
||||
zip.file("applicants.csv", createApplicantsCsv(successfulApplicants))
|
||||
archiveEntries.push({
|
||||
path: "applicants.csv",
|
||||
data: createApplicantsCsv(successfulApplicants)
|
||||
})
|
||||
|
||||
console.log("Creating index.html")
|
||||
zip.file("viewer.html", await getArchiveViewerHtmlSource())
|
||||
archiveEntries.push({
|
||||
path: "viewer.html",
|
||||
data: viewerHtmlSource
|
||||
})
|
||||
|
||||
console.log("Adding viewer Javascript to archive")
|
||||
zip.file("jszip.min.js", await getArchiveViewerJsZipSource())
|
||||
|
||||
archiveEntries.push({
|
||||
path: "fflate.min.js",
|
||||
data: viewerFflateSource
|
||||
})
|
||||
|
||||
console.log("Generating zip archive...")
|
||||
const zipBlob = await zip.generateAsync({ type: "blob" })
|
||||
const zipBlob = await createZipBlob(archiveEntries, ({ phase, processedEntries, totalEntries }) => {
|
||||
if (phase === "preparing") {
|
||||
if (processedEntries === totalEntries || processedEntries === 1 || processedEntries % 10 === 0) {
|
||||
progressDialog.setStatus(`Preparing zip archive (${processedEntries}/${totalEntries})...`)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
progressDialog.setStatus("Generating zip archive in background... Firefox should stay responsive.")
|
||||
})
|
||||
|
||||
console.log("Zip archive is ready.")
|
||||
progressDialog.setStatus("Download ready.")
|
||||
|
|
|
|||
1
lib/fflate.min.js
vendored
Normal file
1
lib/fflate.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
13
lib/jszip.min.js
vendored
13
lib/jszip.min.js
vendored
File diff suppressed because one or more lines are too long
|
|
@ -12,7 +12,7 @@
|
|||
"https://personal.uni-graz.at/*"
|
||||
],
|
||||
"js": [
|
||||
"lib/jszip.min.js",
|
||||
"lib/fflate.min.js",
|
||||
"content.js"
|
||||
],
|
||||
"css": [
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
{
|
||||
"resources": [
|
||||
"archive-viewer/index.html",
|
||||
"lib/jszip.min.js"
|
||||
"lib/fflate.min.js"
|
||||
],
|
||||
"matches": [
|
||||
"https://personal.uni-graz.at/*"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue