Skip to content

Commit

Permalink
fix(Assets): bulk zip downloads broken
Browse files Browse the repository at this point in the history
  • Loading branch information
jakeaturner committed Oct 14, 2024
1 parent 1d77597 commit 157a05d
Show file tree
Hide file tree
Showing 3 changed files with 251 additions and 2 deletions.
2 changes: 1 addition & 1 deletion server/api/validators/projectfiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ export const bulkDownloadProjectFilesSchema = z.object({
projectID: _projectIDSchema,
}),
query: z.object({
fileIDs: z.array(z.string().uuid()),
fileIDs: z.string().max(2200), // allow for approx 50 file IDs in format 'fileID=123&fileID=456&fileID=789', will be parsed by the handling function
emailToNotify: z.string().email(),
}),
});
Expand Down
227 changes: 227 additions & 0 deletions server/util/exports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,230 @@ export function generateWorkSheetColumnDefinitions(
};
});
}

/**
* Attemps to get a file extension from a MIME type. Returns an empty string if not found.
* @param mimeType - the MIME type to get the extension for
* @returns - the file extension (e.g. "pdf" for "application/pdf") or an empty string if not found
*/
export function getFileExtensionFromMimeType(mimeType: string): string {
const found = COMMON_MIME_TYPES.find((cmt) => {
const foundMT = cmt.mimeTypes.find((mt) => mt.value.toLowerCase() === mimeType.toLowerCase());
return foundMT !== undefined;
});
if (found) {
const foundMT = found.mimeTypes.find((mt) => mt.value === mimeType);
if (foundMT && foundMT.extensions) {
return foundMT.extensions[0];
}
}
return "";
}

const COMMON_MIME_TYPES: {
title: string;
anySubType: string;
mimeTypes: {
name: string;
value: string;
extensions?: string[];
}[];
}[] = [
{
title: "Image",
anySubType: "image/*",
mimeTypes: [
{
name: "JPEG",
value: "image/jpeg",
extensions: ["jpg", "jpeg"],
},
{
name: "PNG",
value: "image/png",
extensions: ["png"],
},
{
name: "GIF",
value: "image/gif",
extensions: ["gif"],
},
{
name: "TIFF",
value: "image/tiff",
extensions: ["tiff", "tif"],
},
{
name: "SVG",
value: "image/svg+xml",
extensions: ["svg"],
},
],
},
{
title: "Video",
anySubType: "video/*",
mimeTypes: [
{
name: "AVI",
value: "video/x-msvideo",
extensions: ["avi"],
},
{
name: "FLV",
value: "video/x-flv",
extensions: ["flv"],
},
{
name: "QuickTime (MOV)",
value: "video/quicktime",
extensions: ["mov"],
},
{
name: "MPEG",
value: "video/mpeg",
extensions: ["mpeg", "mpg"],
},
{
name: "WMV",
value: "video/x-ms-wmv",
extensions: ["wmv"],
},
{
name: "MP4",
value: "video/mp4",
extensions: ["mp4"],
},
{
name: "OGG (Video)",
value: "video/ogg",
extensions: ["ogv"],
},
{
name: "WEBM",
value: "video/webm",
extensions: ["webm"],
},
],
},
{
title: "Audio",
anySubType: "audio/*",
mimeTypes: [
{
name: "MP3",
value: "audio/mpeg",
extensions: ["mp3"],
},
{
name: "OGG (Audio)",
value: "audio/ogg",
extensions: ["oga"],
},
{
name: "WAV",
value: "audio/wav",
extensions: ["wav"],
},
],
},
{
title: "Document",
anySubType: "application/*",
mimeTypes: [
{
name: "PDF",
value: "application/pdf",
extensions: ["pdf"],
},
{
name: "Word (DOC)",
value: "application/msword",
extensions: ["doc"],
},
{
name: "Word (DOCX)",
value:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
extensions: ["docx"],
},
{
name: "Excel (XLS)",
value: "application/vnd.ms-excel",
extensions: ["xls"],
},
{
name: "Excel (XLSX)",
value:
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
extensions: ["xlsx"],
},
{
name: "PowerPoint (PPT)",
value: "application/vnd.ms-powerpoint",
extensions: ["ppt"],
},
{
name: "PowerPoint (PPTX)",
value:
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
extensions: ["pptx"],
},
{
name: "JSON",
value: "application/json",
extensions: ["json"],
},
{
name: "XML",
value: "application/xml",
extensions: ["xml"],
},
{
name: "CSV",
value: "text/csv",
extensions: ["csv"],
},
{
name: "Other/Unknown",
value: "application/octet-stream",
},
],
},
{
title: "Text",
anySubType: "text/*",
mimeTypes: [
{
name: "Plain Text",
value: "text/plain",
extensions: ["txt"],
},
{
name: "HTML",
value: "text/html",
extensions: ["html", "htm"],
},
{
name: "CSS",
value: "text/css",
extensions: ["css"],
},
{
name: "JavaScript",
value: "text/javascript",
extensions: ["js"],
},
{
name: "TypeScript",
value: "text/typescript",
extensions: ["ts"],
},
{
name: "LaTeX",
value: "text/x-tex",
extensions: ["tex"],
},
],
},
];
24 changes: 23 additions & 1 deletion server/util/projectutils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import mailAPI from "../api/mail.js";
import { CXOneFetch, getLibUsers, getLibreBotUserId } from "./librariesclient.js";
import MindTouch from "./CXOne/index.js";
import { URLSearchParams } from "url";
import { getFileExtensionFromMimeType } from "./exports.js";

export const projectClassifications = [
"harvesting",
Expand Down Expand Up @@ -955,9 +956,30 @@ export async function parseAndZipS3Objects(
for (let i = 0; i < s3Res.length; i++) {
const byteArray = await s3Res[i].Body?.transformToByteArray();

const getNameWithExtension = (filename: string, mimeType?: string) => {
if(!filename) {
return '';
}

if(filename.includes('.')) {
return filename; // Already has an extension
}

if(!mimeType) {
return filename; // No MIME type to infer extension, return as-is
}

const ext = getFileExtensionFromMimeType(mimeType);
if(!ext) {
return filename; // No extension found, return as-is
}

return `${filename}.${ext}`;
}

if (files[i]) {
items.push({
name: files[i].name,
name: getNameWithExtension(files[i].name || v4(), s3Res[i].ContentType),
data: byteArray,
});
} else {
Expand Down

0 comments on commit 157a05d

Please sign in to comment.