257 lines
7.6 KiB
TypeScript
257 lines
7.6 KiB
TypeScript
const regFileExtension = /(?:\.([^.]+))?$/;
|
|
|
|
export class FileUtil {
|
|
static getExtension(fileName: string): string | undefined {
|
|
return regFileExtension.exec(fileName)[1];
|
|
}
|
|
|
|
static getExtensions(fileList: FileList): string[] {
|
|
const extensions: string[] = [];
|
|
// tslint:disable-next-line: prefer-for-of
|
|
for (let i = 0; i < fileList.length; i++) {
|
|
extensions.push(FileUtil.getExtension(fileList[i].name));
|
|
}
|
|
return extensions;
|
|
}
|
|
|
|
static fromBlobToDataUrl(blob: Blob): Promise<string | ArrayBuffer> {
|
|
return new Promise<string | ArrayBuffer>((resolve, reject) => {
|
|
const fileReader = new FileReader();
|
|
fileReader.onload = () => {
|
|
return resolve(fileReader.result);
|
|
};
|
|
fileReader.onerror = (event: ProgressEvent) => {
|
|
fileReader.abort();
|
|
return reject(fileReader.error);
|
|
};
|
|
fileReader.readAsDataURL(blob);
|
|
});
|
|
}
|
|
|
|
static fromBlobToBuffer(blob: Blob): Promise<Buffer> {
|
|
return new Promise<Buffer>((resolve, reject) => {
|
|
const fileReader = new FileReader();
|
|
fileReader.onload = () => {
|
|
return resolve(Buffer.from(fileReader.result as ArrayBuffer));
|
|
};
|
|
fileReader.onerror = (event: ProgressEvent) => {
|
|
fileReader.abort();
|
|
return reject(fileReader.error);
|
|
};
|
|
fileReader.readAsArrayBuffer(blob);
|
|
});
|
|
}
|
|
|
|
static fromBlobToString(blob: Blob): Promise<string> {
|
|
return new Promise<string>((resolve, reject) => {
|
|
const fileReader = new FileReader();
|
|
fileReader.onload = () => {
|
|
return resolve(fileReader.result.toString());
|
|
};
|
|
fileReader.onerror = (event: ProgressEvent) => {
|
|
fileReader.abort();
|
|
return reject(fileReader.error);
|
|
};
|
|
fileReader.readAsArrayBuffer(blob);
|
|
});
|
|
}
|
|
|
|
static downloadFromBlob(blob: Blob, fileName: string) {
|
|
const a = document.createElement('a');
|
|
document.body.appendChild(a);
|
|
a.style.display = 'none';
|
|
|
|
const url = URL.createObjectURL(blob);
|
|
a.href = url;
|
|
a.download = fileName;
|
|
a.click();
|
|
window.URL.revokeObjectURL(url);
|
|
a.remove();
|
|
}
|
|
|
|
static save(
|
|
buffer: Buffer,
|
|
fileName: string,
|
|
mimeType: string
|
|
): Promise<string> {
|
|
return new Promise<string>((resolve, reject) => {
|
|
const defaultMime = 'application/octet-stream';
|
|
const mime = !!mimeType ? mimeType : defaultMime;
|
|
const blob = new Blob([buffer], { type: mime });
|
|
|
|
if (navigator.msSaveBlob) {
|
|
// IE10+ : (has Blob, but not a[download] or URL)
|
|
navigator.msSaveBlob(blob, fileName);
|
|
resolve(fileName);
|
|
return;
|
|
}
|
|
|
|
const download = (url: string, mode: boolean = false) => {
|
|
const anchor = document.createElement('a');
|
|
|
|
if ('download' in anchor) {
|
|
// html5 A[download]
|
|
anchor.href = url;
|
|
anchor.setAttribute('download', fileName);
|
|
anchor.className = 'download-js-link';
|
|
anchor.innerHTML = 'downloading...';
|
|
anchor.style.display = 'none';
|
|
document.body.appendChild(anchor);
|
|
|
|
setTimeout(() => {
|
|
anchor.click();
|
|
document.body.removeChild(anchor);
|
|
resolve(fileName);
|
|
if (mode) {
|
|
setTimeout(() => {
|
|
window.URL.revokeObjectURL(anchor.href);
|
|
}, 250);
|
|
}
|
|
}, 66);
|
|
return;
|
|
}
|
|
|
|
// handle non-a[download] safari as best we can:
|
|
if (
|
|
/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(
|
|
navigator.userAgent
|
|
)
|
|
) {
|
|
url = url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
|
|
if (!window.open(url)) {
|
|
// popup blocked, offer direct download:
|
|
if (
|
|
confirm(
|
|
'Displaying New Document\n\nUse Save As... to download, then click back to return to this page.'
|
|
)
|
|
) {
|
|
location.href = url;
|
|
}
|
|
}
|
|
resolve(fileName);
|
|
return;
|
|
}
|
|
|
|
// do iframe dataURL download (old ch+FF):
|
|
const f = document.createElement('iframe');
|
|
document.body.appendChild(f);
|
|
|
|
if (!mode) {
|
|
// force a mime that will download:
|
|
url = 'data:' + url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
|
|
}
|
|
f.src = url;
|
|
setTimeout(() => {
|
|
document.body.removeChild(f);
|
|
}, 333);
|
|
};
|
|
|
|
if (window.URL) {
|
|
download(window.URL.createObjectURL(blob), true);
|
|
} else {
|
|
if (
|
|
typeof blob === 'string' ||
|
|
(blob as any).constructor === this.toString
|
|
) {
|
|
try {
|
|
download(
|
|
'data:' + mime + ';base64,' + window.btoa((blob as any) as string)
|
|
);
|
|
} catch (e) {
|
|
download(
|
|
'data:' +
|
|
mime +
|
|
';base64,' +
|
|
encodeURIComponent((blob as any) as string)
|
|
);
|
|
}
|
|
} else {
|
|
const fileReader = new FileReader();
|
|
fileReader.onload = () => {
|
|
download(fileReader.result as string);
|
|
};
|
|
fileReader.readAsDataURL(blob);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
static thumbnail(file: File): Promise<File> {
|
|
return new Promise<File>((resolve, reject) => {
|
|
const fileReader = new FileReader();
|
|
fileReader.onload = () => {
|
|
const blob = new Blob([fileReader.result], { type: file.type });
|
|
const url = URL.createObjectURL(blob);
|
|
const video = document.createElement('video');
|
|
|
|
const snapImage = () =>
|
|
new Promise<Blob>((imgResolve, imgReject) => {
|
|
const canvas = document.createElement('canvas');
|
|
|
|
// thumbnail image resize
|
|
const width = video.videoWidth;
|
|
const height = video.videoHeight;
|
|
let resizeWidth = 0;
|
|
let resizeHeight = 0;
|
|
|
|
// max size
|
|
const maxWidth = 320;
|
|
const maxHeight = 320;
|
|
|
|
if (width > maxWidth || height > maxHeight) {
|
|
if (width > height) {
|
|
resizeWidth = maxWidth;
|
|
resizeHeight = Math.round((height * resizeWidth) / width);
|
|
} else {
|
|
resizeHeight = maxHeight;
|
|
resizeWidth = Math.round((width * resizeHeight) / height);
|
|
}
|
|
} else {
|
|
resizeWidth = width;
|
|
resizeHeight = height;
|
|
}
|
|
|
|
canvas.width = resizeWidth;
|
|
canvas.height = resizeHeight;
|
|
canvas
|
|
.getContext('2d')
|
|
.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
|
|
canvas.toBlob(imgBlob => {
|
|
imgResolve(imgBlob);
|
|
});
|
|
});
|
|
|
|
const timeupdate = () => {
|
|
snapImage().then(imgBlob => {
|
|
video.removeEventListener('timeupdate', timeupdate);
|
|
video.pause();
|
|
resolve(new File([imgBlob], file.name));
|
|
});
|
|
};
|
|
|
|
video.onloadeddata = () => {
|
|
snapImage().then(imgBlob => {
|
|
video.removeEventListener('timeupdate', timeupdate);
|
|
resolve(new File([imgBlob], file.name));
|
|
});
|
|
};
|
|
|
|
video.addEventListener('timeupdate', timeupdate);
|
|
video.preload = 'metadata';
|
|
video.src = url;
|
|
// Load video in Safari / IE11
|
|
video.muted = true;
|
|
// tslint:disable-next-line: no-string-literal
|
|
video['playsInline'] = true;
|
|
video.play();
|
|
};
|
|
fileReader.onerror = (event: ProgressEvent) => {
|
|
fileReader.abort();
|
|
return reject(fileReader.error);
|
|
};
|
|
fileReader.readAsArrayBuffer(file);
|
|
});
|
|
}
|
|
}
|