Skip to content

Commit 1f3f364

Browse files
committed
增加zip上传
1 parent f44c72e commit 1f3f364

4 files changed

Lines changed: 268 additions & 50 deletions

File tree

front/control_panel.html

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -850,10 +850,11 @@ <h3>批量上传认证文件</h3>
850850

851851
<div class="upload-area" id="uploadArea" onclick="document.getElementById('fileInput').click()">
852852
<p>点击选择文件或拖拽文件到此区域</p>
853-
<p style="color: #666; font-size: 14px;">支持 .json 格式文件</p>
853+
<p style="color: #666; font-size: 14px;">支持 .json 和 .zip 格式文件</p>
854+
<p style="color: #888; font-size: 12px;">ZIP文件会自动解压提取其中的JSON凭证</p>
854855
</div>
855856

856-
<input type="file" id="fileInput" multiple accept=".json" style="display: none;" onchange="handleFileSelect(event)" />
857+
<input type="file" id="fileInput" multiple accept=".json,.zip" style="display: none;" onchange="handleFileSelect(event)" />
857858

858859
<div id="fileListSection" class="hidden">
859860
<h4>选择的文件:</h4>
@@ -1665,12 +1666,13 @@ <h3 class="modal-title">设置使用限制</h3>
16651666

16661667
function addFiles(files) {
16671668
files.forEach(file => {
1668-
if (file.type === 'application/json' || file.name.endsWith('.json')) {
1669+
if (file.type === 'application/json' || file.name.endsWith('.json') ||
1670+
file.type === 'application/zip' || file.name.endsWith('.zip')) {
16691671
if (!uploadSelectedFiles.find(f => f.name === file.name && f.size === file.size)) {
16701672
uploadSelectedFiles.push(file);
16711673
}
16721674
} else {
1673-
showStatus(`文件 ${file.name} 不是有效的JSON文件`, 'error');
1675+
showStatus(`文件 ${file.name} 格式不支持,只支持JSON和ZIP文件`, 'error');
16741676
}
16751677
});
16761678

@@ -1692,10 +1694,13 @@ <h3 class="modal-title">设置使用限制</h3>
16921694
uploadSelectedFiles.forEach((file, index) => {
16931695
const fileItem = document.createElement('div');
16941696
fileItem.className = 'file-item';
1697+
const isZip = file.name.endsWith('.zip');
1698+
const fileIcon = isZip ? '📦' : '📄';
1699+
const fileType = isZip ? ' (ZIP压缩包)' : ' (JSON文件)';
16951700
fileItem.innerHTML = `
16961701
<div>
1697-
<span class="file-name">${file.name}</span>
1698-
<span class="file-size">(${formatFileSize(file.size)})</span>
1702+
<span class="file-name">${fileIcon} ${file.name}</span>
1703+
<span class="file-size">(${formatFileSize(file.size)}${fileType})</span>
16991704
</div>
17001705
<button class="remove-btn" onclick="removeFile(${index})">删除</button>
17011706
`;
@@ -1725,6 +1730,22 @@ <h3 class="modal-title">设置使用限制</h3>
17251730
return;
17261731
}
17271732

1733+
// 检查文件大小
1734+
const totalSize = uploadSelectedFiles.reduce((sum, file) => sum + file.size, 0);
1735+
const maxSize = 200 * 1024 * 1024; // 200MB limit
1736+
if (totalSize > maxSize) {
1737+
showStatus(`文件总大小 ${(totalSize/1024/1024).toFixed(1)}MB 超过限制 ${maxSize/1024/1024}MB。请分批上传或删除部分文件。`, 'error');
1738+
return;
1739+
}
1740+
1741+
// 检查单个文件大小
1742+
for (const file of uploadSelectedFiles) {
1743+
if (file.size > 5 * 1024 * 1024) {
1744+
showStatus(`文件 "${file.name}" 大小 ${(file.size/1024/1024).toFixed(1)}MB 超过单文件5MB限制`, 'error');
1745+
return;
1746+
}
1747+
}
1748+
17281749
const progressSection = document.getElementById('uploadProgressSection');
17291750
const progressFill = document.getElementById('progressFill');
17301751
const progressText = document.getElementById('progressText');
@@ -1735,10 +1756,19 @@ <h3 class="modal-title">设置使用限制</h3>
17351756
uploadSelectedFiles.forEach(file => {
17361757
formData.append('files', file);
17371758
});
1759+
1760+
// 检查是否有ZIP文件,给用户提示
1761+
const hasZipFiles = uploadSelectedFiles.some(file => file.name.endsWith('.zip'));
1762+
if (hasZipFiles) {
1763+
showStatus('正在上传并解压ZIP文件...', 'info');
1764+
}
17381765

17391766
try {
17401767
const xhr = new XMLHttpRequest();
17411768

1769+
// 设置超时时间 (5分钟)
1770+
xhr.timeout = 300000;
1771+
17421772
xhr.upload.onprogress = function(event) {
17431773
if (event.lengthComputable) {
17441774
const percentComplete = (event.loaded / event.total) * 100;
@@ -1749,18 +1779,40 @@ <h3 class="modal-title">设置使用限制</h3>
17491779

17501780
xhr.onload = function() {
17511781
if (xhr.status === 200) {
1752-
const data = JSON.parse(xhr.responseText);
1753-
showStatus(`成功上传 ${data.uploaded_count} 个文件`, 'success');
1754-
clearFiles();
1755-
progressSection.classList.add('hidden');
1782+
try {
1783+
const data = JSON.parse(xhr.responseText);
1784+
showStatus(`成功上传 ${data.uploaded_count} 个文件`, 'success');
1785+
clearFiles();
1786+
progressSection.classList.add('hidden');
1787+
} catch (e) {
1788+
showStatus('上传失败: 服务器响应格式错误', 'error');
1789+
}
17561790
} else {
1757-
const error = JSON.parse(xhr.responseText);
1758-
showStatus(`上传失败: ${error.error}`, 'error');
1791+
try {
1792+
const error = JSON.parse(xhr.responseText);
1793+
showStatus(`上传失败: ${error.detail || error.error || '未知错误'}`, 'error');
1794+
} catch (e) {
1795+
showStatus(`上传失败: HTTP ${xhr.status} - ${xhr.statusText || '未知错误'}`, 'error');
1796+
}
17591797
}
17601798
};
17611799

17621800
xhr.onerror = function() {
1763-
showStatus('上传失败:网络错误', 'error');
1801+
console.error('Upload XHR error:', {
1802+
readyState: xhr.readyState,
1803+
status: xhr.status,
1804+
statusText: xhr.statusText,
1805+
responseText: xhr.responseText,
1806+
fileCount: uploadSelectedFiles.length,
1807+
totalSize: (totalSize / 1024 / 1024).toFixed(1) + 'MB'
1808+
});
1809+
showStatus(`上传失败:连接中断 - 可能原因:文件过多(${uploadSelectedFiles.length}个)或网络不稳定。建议分批上传。`, 'error');
1810+
progressSection.classList.add('hidden');
1811+
};
1812+
1813+
xhr.ontimeout = function() {
1814+
showStatus('上传失败:请求超时 - 文件处理时间过长,请减少文件数量或检查网络连接', 'error');
1815+
progressSection.classList.add('hidden');
17641816
};
17651817

17661818
xhr.open('POST', '/auth/upload');

front/control_panel_mobile.html

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -562,10 +562,11 @@ <h3>批量上传认证文件</h3>
562562

563563
<div style="border: 2px dashed #ddd; border-radius: 8px; padding: 30px; text-align: center; background-color: #fafafa; margin: 20px 0; cursor: pointer; transition: border-color 0.3s;" id="uploadArea" onclick="document.getElementById('fileInput').click()">
564564
<p style="margin: 10px 0; font-size: 16px;">📁 点击选择文件或拖拽文件到此区域</p>
565-
<p style="color: #666; font-size: 14px; margin: 5px 0;">支持 .json 格式文件</p>
565+
<p style="color: #666; font-size: 14px; margin: 5px 0;">支持 .json 和 .zip 格式文件</p>
566+
<p style="color: #888; font-size: 12px; margin: 5px 0;">ZIP文件会自动解压提取其中的JSON凭证</p>
566567
</div>
567568

568-
<input type="file" id="fileInput" multiple accept=".json" style="display: none;" onchange="handleFileSelect(event)" />
569+
<input type="file" id="fileInput" multiple accept=".json,.zip" style="display: none;" onchange="handleFileSelect(event)" />
569570

570571
<div id="fileListSection" class="hidden">
571572
<h4>选择的文件:</h4>
@@ -1441,12 +1442,13 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
14411442

14421443
function addFiles(files) {
14431444
files.forEach(file => {
1444-
if (file.type === 'application/json' || file.name.endsWith('.json')) {
1445+
if (file.type === 'application/json' || file.name.endsWith('.json') ||
1446+
file.type === 'application/zip' || file.name.endsWith('.zip')) {
14451447
if (!uploadSelectedFiles.find(f => f.name === file.name && f.size === file.size)) {
14461448
uploadSelectedFiles.push(file);
14471449
}
14481450
} else {
1449-
showStatus(`文件 ${file.name} 不是有效的JSON文件`, 'error');
1451+
showStatus(`文件 ${file.name} 格式不支持,只支持JSON和ZIP文件`, 'error');
14501452
}
14511453
});
14521454

@@ -1468,10 +1470,13 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
14681470
uploadSelectedFiles.forEach((file, index) => {
14691471
const fileItem = document.createElement('div');
14701472
fileItem.style.cssText = 'background-color: #f8f9fa; border: 1px solid #e1e4e8; border-radius: 6px; padding: 10px; margin: 5px 0; display: flex; justify-content: space-between; align-items: center;';
1473+
const isZip = file.name.endsWith('.zip');
1474+
const fileIcon = isZip ? '📦' : '📄';
1475+
const fileType = isZip ? ' (ZIP压缩包)' : ' (JSON文件)';
14711476
fileItem.innerHTML = `
14721477
<div>
1473-
<span style="font-family: monospace; color: #333; font-size: 14px;">${file.name}</span>
1474-
<span style="color: #666; font-size: 12px; margin-left: 10px;">(${formatFileSize(file.size)})</span>
1478+
<span style="font-family: monospace; color: #333; font-size: 14px;">${fileIcon} ${file.name}</span>
1479+
<span style="color: #666; font-size: 12px; margin-left: 10px;">(${formatFileSize(file.size)}${fileType})</span>
14751480
</div>
14761481
<button onclick="removeFile(${index})" style="background: #dc3545; color: white; border: none; border-radius: 4px; padding: 4px 8px; cursor: pointer; font-size: 12px;">删除</button>
14771482
`;
@@ -1501,6 +1506,22 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
15011506
return;
15021507
}
15031508

1509+
// 检查文件大小
1510+
const totalSize = uploadSelectedFiles.reduce((sum, file) => sum + file.size, 0);
1511+
const maxSize = 200 * 1024 * 1024; // 200MB limit
1512+
if (totalSize > maxSize) {
1513+
showStatus(`文件总大小 ${(totalSize/1024/1024).toFixed(1)}MB 超过限制 ${maxSize/1024/1024}MB。请分批上传或删除部分文件。`, 'error');
1514+
return;
1515+
}
1516+
1517+
// 检查单个文件大小
1518+
for (const file of uploadSelectedFiles) {
1519+
if (file.size > 5 * 1024 * 1024) {
1520+
showStatus(`文件 "${file.name}" 大小 ${(file.size/1024/1024).toFixed(1)}MB 超过单文件5MB限制`, 'error');
1521+
return;
1522+
}
1523+
}
1524+
15041525
const progressSection = document.getElementById('uploadProgressSection');
15051526
const progressFill = document.getElementById('progressFill');
15061527
const progressText = document.getElementById('progressText');
@@ -1511,10 +1532,19 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
15111532
uploadSelectedFiles.forEach(file => {
15121533
formData.append('files', file);
15131534
});
1535+
1536+
// 检查是否有ZIP文件,给用户提示
1537+
const hasZipFiles = uploadSelectedFiles.some(file => file.name.endsWith('.zip'));
1538+
if (hasZipFiles) {
1539+
showStatus('正在上传并解压ZIP文件...', 'info');
1540+
}
15141541

15151542
try {
15161543
const xhr = new XMLHttpRequest();
15171544

1545+
// 设置超时时间 (5分钟)
1546+
xhr.timeout = 300000;
1547+
15181548
xhr.upload.onprogress = function(event) {
15191549
if (event.lengthComputable) {
15201550
const percentComplete = (event.loaded / event.total) * 100;
@@ -1525,18 +1555,40 @@ <h3 style="margin: 0; font-size: 16px; color: #333;">设置使用限制</h3>
15251555

15261556
xhr.onload = function() {
15271557
if (xhr.status === 200) {
1528-
const data = JSON.parse(xhr.responseText);
1529-
showStatus(`成功上传 ${data.uploaded_count} 个文件`, 'success');
1530-
clearFiles();
1531-
progressSection.classList.add('hidden');
1558+
try {
1559+
const data = JSON.parse(xhr.responseText);
1560+
showStatus(`成功上传 ${data.uploaded_count} 个文件`, 'success');
1561+
clearFiles();
1562+
progressSection.classList.add('hidden');
1563+
} catch (e) {
1564+
showStatus('上传失败: 服务器响应格式错误', 'error');
1565+
}
15321566
} else {
1533-
const error = JSON.parse(xhr.responseText);
1534-
showStatus(`上传失败: ${error.error}`, 'error');
1567+
try {
1568+
const error = JSON.parse(xhr.responseText);
1569+
showStatus(`上传失败: ${error.detail || error.error || '未知错误'}`, 'error');
1570+
} catch (e) {
1571+
showStatus(`上传失败: HTTP ${xhr.status} - ${xhr.statusText || '未知错误'}`, 'error');
1572+
}
15351573
}
15361574
};
15371575

15381576
xhr.onerror = function() {
1539-
showStatus('上传失败:网络错误', 'error');
1577+
console.error('Upload XHR error:', {
1578+
readyState: xhr.readyState,
1579+
status: xhr.status,
1580+
statusText: xhr.statusText,
1581+
responseText: xhr.responseText,
1582+
fileCount: uploadSelectedFiles.length,
1583+
totalSize: (totalSize / 1024 / 1024).toFixed(1) + 'MB'
1584+
});
1585+
showStatus(`上传失败:连接中断 - 可能原因:文件过多(${uploadSelectedFiles.length}个)或网络不稳定。建议分批上传。`, 'error');
1586+
progressSection.classList.add('hidden');
1587+
};
1588+
1589+
xhr.ontimeout = function() {
1590+
showStatus('上传失败:请求超时 - 文件处理时间过长,请减少文件数量或检查网络连接', 'error');
1591+
progressSection.classList.add('hidden');
15401592
};
15411593

15421594
xhr.open('POST', '/auth/upload');

0 commit comments

Comments
 (0)