file.js

import { safeData } from './base.js';

/**
 * @module index
 * @author linjielinlin 993353454@qq.com
 * @date 2022-05-11 22:07:43
 * @description 文件相关处理
 */
/**
 * @function blobToBase64
 * @description 将Blob对象转换为base64字符串
 * @date 2020-03-01
 * @param {Blob} argBlob 需要处理的Blob对象
 * @returns {Promise} 返回base64字符串
 * @example
 * blobToBase64(blob).then(base64 => console.log(base64));
 */
const blobToBase64 = async (argBlob) => {
    return new Promise(function (resolve, reject) {
        const fileReader = new FileReader();
        fileReader.readAsDataURL(argBlob);
        fileReader.onload = (e) => {
            return resolve(e?.target?.result);
        };
        fileReader.onerror = () => {
            return reject(new Error('文件流异常'));
        };
    });
};
/**
 * @function blobUrlToFile
 * @description 将blobUrl转换为File对象
 * @date 2020-03-01
 * @param {string} argData blobUrl
 * @returns {Promise} 返回File对象
 * @example
 * blobUrlToFile(url).then(file => console.log(file));
 */
const blobUrlToFile = async (argData) => {
    return new Promise(function (resolve, reject) {
        // eslint-disable-next-line no-undef
        var xhr = new XMLHttpRequest();
        xhr.open('GET', argData, true);
        xhr.responseType = 'blob';
        xhr.onload = function (e) {
            if (this.status === 200) {
                return resolve(this.response);
            }
        };
        xhr.onerror = (err) => {
            return reject(err);
        };
        xhr.send();
    });
};
/**
 * @function dataURLtoBlob
 * @description 将图片的dataUrl base64转换为Blob对象
 * @param {string} argData dataUrl
 * @returns {Blob} 返回Blob对象
 * @example
 * const blob = dataURLtoBlob(dataUrl);
 */
const dataURLtoBlob = (argData) => {
    if (!argData.match(/;base64,/)) {
        return new Blob();
    }
    let arr = argData.split(',');
    let mime = safeData(arr[0].match(/:(.*?);/), '1', '');
    if (!mime) {
        return new Blob();
    }
    let bstr = globalThis.atob(arr[1]);
    let n = bstr.length;
    let u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
};
/**
 * @function blobToFile
 * @description 将Blob对象转换为File对象
 * @param {Blob} argBlob Blob对象
 * @param {string} argName 文件名,默认为当前时间戳
 * @returns {File} 返回File对象
 * @example
 * const file = blobToFile(blob, 'example.txt');
 */
const blobToFile = (argBlob, argName = Date.now().toString()) => {
    let file = new File([argBlob], argName, {
        type: argBlob.type,
    });
    return file;
};
/**
 * @function dlFile
 * @description 下载文件
 * @param {string|Blob|File} argData Blob对象/File对象/dataUrl/base64
 * @param {string} argName 文件名
 * @param {number} argDelTime 移除dateUrl时间
 * @example
 * dlFile(data, 'example.txt', 10000);
 */
const dlFile = (argData, argName = Date.now().toString(), argDelTime = 10000) => {
    let downNode = globalThis.document.createElement('a');
    downNode.download = argName;
    // 字符内容转换为blob地址
    let href = '';
    if (typeof argData === 'string') {
        if (argData.startsWith('blob:')) {
            href = argData;
        }
        else if (argData.startsWith('data:')) {
            href = argData;
        }
        argData = new Blob([argData]);
    }
    href = href || URL.createObjectURL(argData);
    downNode.href = href;
    setTimeout(() => {
        URL.revokeObjectURL(href);
    }, argDelTime);
    globalThis.document.body.appendChild(downNode);
    downNode.click();
    globalThis.document.body.removeChild(downNode);
};
/**
 * @function getDuration
 * @description 获取音视频文件的时长
 * @param {Blob|File|string} argFile 音视频数据,如果是string类型,则为链接
 * @returns {Promise} 返回时长(单位:秒)
 * @example
 * getDuration(file).then(duration => console.log(duration));
 */
const getDuration = async (argFile) => {
    let filePath;
    if (typeof argFile === 'string') {
        filePath = argFile;
    }
    else {
        filePath = URL.createObjectURL(argFile);
    }
    return new Promise((resolve, reject) => {
        const audio = new Audio(filePath);
        audio.addEventListener('loadedmetadata', function (e) {
            if (filePath.startsWith('blob:')) {
                URL.revokeObjectURL(filePath);
            }
            const duration = audio.duration;
            audio.src = '';
            return resolve(duration);
        });
        setTimeout(() => {
            return reject(new Error('读取时长超时'));
        }, 5000);
    });
};
/**
 * @function loadFile
 * @description 动态加载html文件标签
 * @param {string} argUrl 要加载的url
 * @param {string} argType 加载类型 js/css
 * @param {object} argOptions
 * @param {string} argOption.disCheck 不检查是否有相同标签
 * @param {string} argOption.force 是否强制添加,true时先删除再添加
 * @return {Promise} 返回Promise对象
 * @example
 * loadFile(url, 'js', {force: true}).then(() => console.log('Loaded'));
 */
const loadFile = (argUrl, argType = 'js', argOptions = {}) => {
    let temId = argType + '-' + argUrl.split('/').pop();
    let head = globalThis.document.getElementsByTagName('head')[0];
    let nodeTag;
    if (!argOptions.disCheck) {
        let checkTag = globalThis.document.getElementById(temId);
        // 已经存在对应tag
        if (checkTag) {
            if (argOptions.force) {
                head.removeChild(checkTag);
            }
            else {
                return Promise.resolve({ msg: '已存在,中断加载!' });
            }
        }
    }
    switch (argType) {
        case 'css':
            nodeTag = globalThis.document.createElement('link');
            nodeTag.type = 'text/css';
            nodeTag.rel = 'stylesheet';
            nodeTag.href = argUrl;
            break;
        case 'js':
            nodeTag = globalThis.document.createElement('script');
            nodeTag.src = argUrl;
            nodeTag.type = 'text/javascript';
            break;
        default:
            console.error('暂不支持:' + argType);
            return Promise.reject({ msg: '暂不支持:' + argType });
    }
    nodeTag.id = temId;
    head.appendChild(nodeTag);
    return new Promise((resolve) => {
        if (nodeTag.readyState) {
            nodeTag.onreadystatechange = function () {
                if (nodeTag.readyState === 'complete') {
                    nodeTag.onreadystatechange = null;
                    return resolve(argUrl);
                }
            };
        }
        else {
            // Others
            nodeTag.onload = function () {
                return resolve(argUrl);
            };
        }
    });
};

export { blobToBase64, blobToFile, blobUrlToFile, dataURLtoBlob, dlFile, getDuration, loadFile };