apps/meteor/client/lib/download.ts
export const download = (href: string, filename: string): void => {
const anchorElement = document.createElement('a');
anchorElement.download = filename;
anchorElement.href = href;
anchorElement.target = '_blank';
document.body.appendChild(anchorElement);
anchorElement.click();
document.body.removeChild(anchorElement);
};
const hasMsSaveOrOpenBlob = (navigator: Navigator): navigator is Navigator & { msSaveOrOpenBlob: (blob: Blob) => void } =>
'msSaveOrOpenBlob' in navigator;
export const downloadAs = ({ data, ...options }: { data: BlobPart[] } & BlobPropertyBag, filename: string): void => {
const blob = new Blob(data, options);
if (hasMsSaveOrOpenBlob(navigator)) {
navigator.msSaveOrOpenBlob(blob);
return;
}
const URL = window.webkitURL ?? window.URL;
const blobUrl = URL.createObjectURL(blob);
download(blobUrl, filename);
URL.revokeObjectURL(blobUrl);
};
export const downloadJsonAs = (jsonObject: unknown, basename: string): void => {
downloadAs(
{
data: [decodeURIComponent(encodeURI(JSON.stringify(jsonObject, null, 2)))],
type: 'application/json;charset=utf-8',
},
`${basename}.json`,
);
};
export const downloadCsvAs = (csvData: readonly (readonly unknown[])[], basename: string): void => {
const escapeCell = (cell: unknown): string => `"${String(cell).replace(/"/g, '""')}"`;
const content = csvData.reduce((content, row) => `${content + row.map(escapeCell).join(';')}\n`, '');
downloadAs(
{
data: [decodeURIComponent(encodeURI(content))],
type: 'text/csv;charset=utf-8',
endings: 'native',
},
`${basename}.csv`,
);
};