From 1df4c2f070e8105aedf16437f8124b4d692b47d0 Mon Sep 17 00:00:00 2001
From: Tevin <tingquanren@163.com>
Date: Sat, 16 Jul 2022 18:55:03 +0800
Subject: [PATCH] 实现文件转换组件

---
 common/FileTransform.js |  148 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/common/FileTransform.js b/common/FileTransform.js
new file mode 100644
index 0000000..cc35f73
--- /dev/null
+++ b/common/FileTransform.js
@@ -0,0 +1,148 @@
+/**
+ * 文件转换
+ * @author Tevin
+ */
+
+import moment from 'moment';
+
+export class FileTransform {
+
+    constructor() {
+        this._data = {
+            chunkSize: 20 * 1024,
+        };
+    }
+
+    getChunkSize() {
+        return this._data.chunkSize;
+    }
+
+    setChunkSize() {
+        return this._data.chunkSize;
+    }
+
+    /**
+     * 转换 ObjectURL 为 base64 数据体
+     * @param objUrl
+     * @param callback
+     */
+    transObjUrlToBaseData(objUrl, callback) {
+        this.convertObjectUrlToBlob(objUrl, blob => {
+            this.convertBlobToBase64(blob, base64 => {
+                const mime = base64.split(',')[0].match(/:(.*?);/)[1];
+                const fileName = this._makeFileName(mime);
+                const baseArr = this.splitBase64ToArray(base64);
+                callback && callback({
+                    fileName,
+                    baseArr,
+                    total: baseArr.length,
+                });
+            });
+        });
+    }
+
+    /**
+     * 转换 base64 数据体为 ObjectURL
+     * @param baseData
+     * @param callback
+     */
+    transBaseDataToObjUrl(baseData, callback) {
+        const base64 = baseData.baseArr.join('');
+        this.convertBase64ToFile(base64, baseData.fileName, file => {
+            this.convertFileToObjectUrl(file, objUrl => {
+                callback && callback(objUrl);
+            });
+        });
+    }
+
+    convertBlobToBase64(blob, callback) {
+        const reader = new FileReader();
+        reader.onload = evt => {
+            callback && callback(evt.target.result);
+        };
+        reader.readAsDataURL(blob);
+    }
+
+    convertObjectUrlToBlob(objUrl, callback) {
+        const xhr = new XMLHttpRequest();
+        xhr.open('GET', objUrl, true);
+        xhr.responseType = 'blob';
+        xhr.onload = function () {
+            if (this.status === 200) {
+                callback && callback(this.response);
+            } else {
+                /* eslint-disable prefer-promise-reject-errors */
+                callback && callback(null, { status: this.status });
+            }
+        };
+        xhr.send();
+    }
+
+    convertBase64ToFile(base64, fileName, callback) {
+        const arr = base64.split(',');
+        const mime = arr[0].match(/:(.*?);/)[1];
+        const bstr = atob(arr[1]);
+        let n = bstr.length;
+        const u8arr = new Uint8Array(n);
+        while (n--) {
+            u8arr[n] = bstr.charCodeAt(n);
+        }
+        fileName = fileName || this._makeFileName(mime);
+        const file = new File([u8arr], fileName, { type: mime });
+        callback && callback(file);
+    }
+
+    convertFileToObjectUrl(file, callback) {
+        let URLMaker = URL;
+        if (window) {
+            URLMaker = window.URL || window.webkitURL;
+        }
+        const url = URLMaker.createObjectURL(file);
+        callback && callback(url);
+    }
+
+    // 生成文件名
+    _makeFileName(mime) {
+        const curMoment = moment();
+        const name = 'IMG' + curMoment.format('-YYYYMMDD-HHmmss-') +
+            curMoment.format('x').substr(-3) + '-' + parseInt(Math.random() * 10000);
+        const mimeTypes = {
+            'image/jpeg': 'jpg',
+            'image/gif': 'gif',
+            'image/png': 'png',
+            'image/svg+xml': 'svg',
+            'image/webp': 'webp',
+            'image/tiff': 'tif',
+            'text/plain': 'txt',
+            'text/css': 'css',
+            'text/html': 'html',
+            'text/xml': 'xml',
+            'text/javascript': 'js',
+            'application/x-javascript': 'js',
+            'audio/mpeg': 'mp3',
+            'video/mp4': 'mp4',
+            'video/webm': 'webm',
+            'application/zip': 'zip',
+            'application/rar': 'rar',
+            'application/pdf': 'pdf',
+            'application/rtf': 'rtf',
+        };
+        return name + '.' + mimeTypes[mime];
+    }
+
+    splitBase64ToArray(base64) {
+        const count = Math.ceil(base64.length / this._data.chunkSize);
+        if (count === 1) {
+            return [base64];
+        }
+        const array = [];
+        for (let i = 0; i < count; i++) {
+            const chunk = base64.substr(this._data.chunkSize * i, this._data.chunkSize);
+            array.push(chunk);
+        }
+        return array;
+    }
+
+}
+
+export const $fileTrans = new FileTransform();
\ No newline at end of file

--
Gitblit v1.9.1