240 lines
5.7 KiB
JavaScript
240 lines
5.7 KiB
JavaScript
var G3FileUtils = {
|
|
/**
|
|
* 格式化文件大小
|
|
* @param {number} bytes - 文件大小(字节)
|
|
* @returns {string} 格式化后的大小
|
|
*/
|
|
formatFileSize: function (bytes) {
|
|
var numBytes = typeof bytes === "string" ? parseFloat(bytes) : bytes;
|
|
if (
|
|
numBytes === null ||
|
|
numBytes === undefined ||
|
|
isNaN(numBytes) ||
|
|
numBytes <= 0
|
|
) {
|
|
return "-";
|
|
}
|
|
|
|
var k = 1024;
|
|
var sizes = ["B", "KB", "MB", "GB", "TB"];
|
|
|
|
var i = Math.floor(Math.log(numBytes) / Math.log(k));
|
|
i = Math.max(0, Math.min(i, sizes.length - 1));
|
|
|
|
return (numBytes / Math.pow(k, i)).toFixed(2) + " " + sizes[i];
|
|
},
|
|
|
|
/**
|
|
* 格式化日期
|
|
* @param {string} dateStr - 日期字符串
|
|
* @returns {string} 格式化后的日期
|
|
*/
|
|
formatDate: function (dateStr) {
|
|
if (!dateStr) return "-";
|
|
|
|
var date = new Date(dateStr);
|
|
|
|
if (isNaN(date.getTime())) {
|
|
return "-";
|
|
}
|
|
|
|
var year = date.getFullYear();
|
|
var month = ("0" + (date.getMonth() + 1)).slice(-2);
|
|
var day = ("0" + date.getDate()).slice(-2);
|
|
var hours = ("0" + date.getHours()).slice(-2);
|
|
var minutes = ("0" + date.getMinutes()).slice(-2);
|
|
var seconds = ("0" + date.getSeconds()).slice(-2);
|
|
|
|
return (
|
|
year +
|
|
"-" +
|
|
month +
|
|
"-" +
|
|
day +
|
|
" " +
|
|
hours +
|
|
":" +
|
|
minutes +
|
|
":" +
|
|
seconds
|
|
);
|
|
},
|
|
|
|
/**
|
|
* 判断是否为图片文件
|
|
* @param {string} filename - 文件名
|
|
* @returns {boolean} 是否为图片文件
|
|
*/
|
|
isImageFile: function (filename) {
|
|
if (!filename || typeof filename !== "string") return false;
|
|
|
|
const ext = filename.slice(filename.lastIndexOf(".") + 1).toLowerCase();
|
|
const imageExts = new Set(["jpg", "jpeg", "png", "gif", "bmp", "webp"]);
|
|
|
|
return imageExts.has(ext);
|
|
},
|
|
|
|
/**
|
|
* 获取文件图标
|
|
* @param {string} filename - 文件名
|
|
* @returns {string} 图标HTML
|
|
*/
|
|
getFileIcon: function (filename) {
|
|
var ext = filename.split(".").pop().toLowerCase();
|
|
|
|
if (this.isImageFile(filename)) {
|
|
return "";
|
|
}
|
|
|
|
// 根据不同的文件类型显示不同的图标
|
|
const audioTypes = ["mp3", "wav", "aac", "flac", "ogg"];
|
|
if (audioTypes.includes(ext)) {
|
|
return G3FileIcons.file.audio;
|
|
}
|
|
|
|
// 视频类型
|
|
const videoTypes = ["mp4", "avi", "mkv", "mov", "wmv"];
|
|
if (videoTypes.includes(ext)) {
|
|
return G3FileIcons.file.video;
|
|
}
|
|
|
|
if (ext === "txt") {
|
|
return G3FileIcons.file.txt;
|
|
}
|
|
|
|
if (ext === "pdf") {
|
|
return G3FileIcons.file.pdf;
|
|
}
|
|
|
|
// 文档类型
|
|
const documentTypes = ["docx", "xlsx", "pptx", "office"];
|
|
if (documentTypes.includes(ext)) {
|
|
return G3FileIcons.file.docs;
|
|
}
|
|
|
|
// 压缩包类型
|
|
const archiveTypes = ["zip", "rar", "tar", "gz"];
|
|
if (archiveTypes.includes(ext)) {
|
|
return G3FileIcons.file.zip;
|
|
}
|
|
|
|
return G3FileIcons.file.default;
|
|
},
|
|
|
|
/**
|
|
* 获取唯一文件名
|
|
* @param {string} fileName - 原始文件名
|
|
* @param {Set} files - 已存在的文件名集合
|
|
* @returns {string} 唯一文件名
|
|
*/
|
|
getUniqueFileName: function (fileName, files) {
|
|
const originalFileName = fileName;
|
|
let uniqueFileName = fileName;
|
|
let counter = 1;
|
|
|
|
while (files.has(uniqueFileName)) {
|
|
const fileNameWithoutExtension = originalFileName.replace(
|
|
/\.[^/.]+$/,
|
|
"",
|
|
);
|
|
const extension = originalFileName.slice(
|
|
originalFileName.lastIndexOf("."),
|
|
);
|
|
uniqueFileName = `${fileNameWithoutExtension} (${counter})${extension}`;
|
|
counter++;
|
|
}
|
|
|
|
return uniqueFileName;
|
|
},
|
|
|
|
/**
|
|
* 压缩图片
|
|
* @param {File} file - 图片文件
|
|
* @param {Object} options - 压缩选项
|
|
* @returns {Promise<File|Blob>} 压缩后的文件
|
|
*/
|
|
compressImage: async function (file, options = {}) {
|
|
const {
|
|
minSize = 300 * 1024,
|
|
maxSize = 1.2 * 1024 * 1024,
|
|
maxWidth = 1920,
|
|
maxHeight = 1920,
|
|
} = options;
|
|
|
|
if (!file || !file.type.startsWith("image/")) return file;
|
|
|
|
const originSize = file.size;
|
|
|
|
if (originSize <= maxSize) {
|
|
return file;
|
|
}
|
|
|
|
const img = await new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.onload = () => {
|
|
const image = new Image();
|
|
image.onload = () => resolve(image);
|
|
image.onerror = reject;
|
|
image.src = reader.result;
|
|
};
|
|
reader.onerror = reject;
|
|
reader.readAsDataURL(file);
|
|
});
|
|
|
|
const canvas = document.createElement("canvas");
|
|
const ctx = canvas.getContext("2d");
|
|
|
|
let w = img.width;
|
|
let h = img.height;
|
|
|
|
const scale = Math.min(1, maxWidth / w, maxHeight / h);
|
|
w = Math.round(w * scale);
|
|
h = Math.round(h * scale);
|
|
|
|
canvas.width = w;
|
|
canvas.height = h;
|
|
ctx.drawImage(img, 0, 0, w, h);
|
|
|
|
const getBlob = (q) =>
|
|
new Promise((resolve) => {
|
|
canvas.toBlob((b) => resolve(b), "image/jpeg", q);
|
|
});
|
|
|
|
let quality = 0.92;
|
|
|
|
if (originSize > 4 * 1024 * 1024) {
|
|
quality = 0.88;
|
|
}
|
|
|
|
const blob = await getBlob(quality);
|
|
|
|
if (blob && blob.size < minSize) {
|
|
const safe = await getBlob(0.97);
|
|
return safe || file;
|
|
}
|
|
|
|
return blob || file;
|
|
},
|
|
|
|
/**
|
|
* 生成唯一ID
|
|
* @returns {string} 唯一ID
|
|
*/
|
|
generateUniqueId: function () {
|
|
return "file_" + Math.random().toString(36).slice(2) + Date.now();
|
|
},
|
|
|
|
/**
|
|
* Base64 编码
|
|
* @param {string} str - 字符串
|
|
* @returns {string} Base64 编码结果
|
|
*/
|
|
base64Encode: function (str) {
|
|
return btoa(
|
|
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
|
return String.fromCharCode("0x" + p1);
|
|
}),
|
|
);
|
|
},
|
|
};
|