修复安卓手机显示名称不符显示为linux的问题;修复文件名乱码的问题

This commit is contained in:
2026-03-28 19:13:22 +08:00
parent 3d391415c6
commit 8b5f7d517e
5 changed files with 92 additions and 28 deletions

View File

@@ -456,6 +456,7 @@ func (h *HTTPHandler) downloadFallback(c *gin.Context) {
defer cancel() defer cancel()
filename := filepath.Base(transfer.Name) filename := filepath.Base(transfer.Name)
filename = decodeDownloadFilename(filename)
if filename == "." || filename == "" { if filename == "." || filename == "" {
filename = "download.bin" filename = "download.bin"
} }
@@ -597,6 +598,19 @@ func contentDisposition(filename string) string {
return `attachment; filename="` + escaped + `"` return `attachment; filename="` + escaped + `"`
} }
func decodeDownloadFilename(filename string) string {
filename = strings.TrimSpace(filename)
if filename == "" || !strings.Contains(filename, "%") {
return filename
}
decoded, err := url.PathUnescape(filename)
if err != nil {
return filename
}
return strings.TrimSpace(decoded)
}
func (h *HTTPHandler) ensureFallbackBucket(ctx context.Context, transferID string) error { func (h *HTTPHandler) ensureFallbackBucket(ctx context.Context, transferID string) error {
if h.deps.MinIOClient == nil { if h.deps.MinIOClient == nil {
return nil return nil

17
frontend/dist/assets/index-BoiTbES-.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AirShare Pro</title> <title>AirShare Pro</title>
<script type="module" crossorigin src="/assets/index-DPzeYqvr.js"></script> <script type="module" crossorigin src="/assets/index-BoiTbES-.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-C-7tVt-S.css"> <link rel="stylesheet" crossorigin href="/assets/index-C-7tVt-S.css">
</head> </head>
<body> <body>

View File

@@ -302,6 +302,7 @@ async function loadPendingDownloads() {
const downloads = await devicesApi.listPendingDownloads(localDevice.value.id) const downloads = await devicesApi.listPendingDownloads(localDevice.value.id)
pendingDownloads.value = downloads.map((item) => ({ pendingDownloads.value = downloads.map((item) => ({
...item, ...item,
name: normalizeDisplayName(item.name),
download_path: item.download_path || `/api/transfers/${encodeURIComponent(item.transfer_id)}/fallback/download`, download_path: item.download_path || `/api/transfers/${encodeURIComponent(item.transfer_id)}/fallback/download`,
size_label: formatFileSize(Number(item.size_bytes || 0)), size_label: formatFileSize(Number(item.size_bytes || 0)),
created_label: formatRelativeTime(item.created_at), created_label: formatRelativeTime(item.created_at),
@@ -551,7 +552,7 @@ function addFiles(files) {
id: createId(`file-${index}`), id: createId(`file-${index}`),
kind: 'file', kind: 'file',
file, file,
name: file.name, name: normalizeDisplayName(file.name),
size: formatFileSize(file.size), size: formatFileSize(file.size),
sizeBytes: file.size, sizeBytes: file.size,
status: '待发送', status: '待发送',
@@ -1166,15 +1167,47 @@ function ensureDeviceId() {
function ensureDeviceName(deviceId) { function ensureDeviceName(deviceId) {
let deviceName = localStorage.getItem(DEVICE_NAME_KEY) let deviceName = localStorage.getItem(DEVICE_NAME_KEY)
if (!deviceName) { if (!deviceName || isLegacyAutoDeviceName(deviceName, deviceId)) {
const platform = navigator.userAgentData?.platform || navigator.platform || 'Web' deviceName = `${detectDeviceLabel()} ${deviceId.slice(0, 4)}`
deviceName = `${platform} ${deviceId.slice(0, 4)}`
localStorage.setItem(DEVICE_NAME_KEY, deviceName) localStorage.setItem(DEVICE_NAME_KEY, deviceName)
} }
return deviceName return deviceName
} }
function isLegacyAutoDeviceName(deviceName, deviceId) {
const value = String(deviceName || '').trim()
const suffix = deviceId.slice(0, 4)
if (!value || !suffix || !value.endsWith(` ${suffix}`)) {
return false
}
return /^(android|iphone|ipad|linux|macintel|macos|windows|win32|web)\s/i.test(value)
}
function detectDeviceLabel() {
const source = `${navigator.userAgent} ${navigator.platform}`.toLowerCase()
if (source.includes('iphone')) {
return 'iPhone'
}
if (source.includes('ipad')) {
return 'iPad'
}
if (source.includes('android')) {
return 'Android'
}
if (source.includes('windows') || source.includes('win32')) {
return 'Windows'
}
if (source.includes('mac os') || source.includes('macintosh') || source.includes('macintel')) {
return 'macOS'
}
if (source.includes('linux')) {
return 'Linux'
}
return 'Web'
}
function detectDeviceType() { function detectDeviceType() {
const source = `${navigator.userAgent} ${navigator.platform}`.toLowerCase() const source = `${navigator.userAgent} ${navigator.platform}`.toLowerCase()
if (source.includes('iphone') || source.includes('android') || source.includes('mobile')) { if (source.includes('iphone') || source.includes('android') || source.includes('mobile')) {
@@ -1186,6 +1219,23 @@ function detectDeviceType() {
return 'desktop' return 'desktop'
} }
function normalizeDisplayName(value, fallback = 'file') {
const raw = String(value || '').trim()
if (!raw) {
return fallback
}
if (!/%[0-9A-Fa-f]{2}/.test(raw)) {
return raw
}
try {
return decodeURIComponent(raw)
} catch {
return raw
}
}
function mapDeviceIcon(type) { function mapDeviceIcon(type) {
if (type === 'phone') { if (type === 'phone') {
return 'smartphone' return 'smartphone'
@@ -1600,7 +1650,7 @@ function handleIncomingRealtimeFileMeta(payload) {
ensurePeerSession(sender, true) ensurePeerSession(sender, true)
incomingFileBuffers.set(payload.transfer_id, { incomingFileBuffers.set(payload.transfer_id, {
name: payload.name || 'file', name: normalizeDisplayName(payload.name, 'file'),
mimeType: payload.mime_type || 'application/octet-stream', mimeType: payload.mime_type || 'application/octet-stream',
sizeBytes: Number(payload.size_bytes || 0), sizeBytes: Number(payload.size_bytes || 0),
receivedBytes: 0, receivedBytes: 0,
@@ -1613,7 +1663,7 @@ function handleIncomingRealtimeFileMeta(payload) {
id: createId('incoming-file'), id: createId('incoming-file'),
transferId: payload.transfer_id, transferId: payload.transfer_id,
kind: 'file', kind: 'file',
name: payload.name || 'file', name: normalizeDisplayName(payload.name, 'file'),
size: formatFileSize(Number(payload.size_bytes || 0)), size: formatFileSize(Number(payload.size_bytes || 0)),
sizeBytes: Number(payload.size_bytes || 0), sizeBytes: Number(payload.size_bytes || 0),
status: '正在接收...', status: '正在接收...',
@@ -1965,7 +2015,7 @@ function handleIncomingTransferCreated(envelope) {
id: createId('incoming-file'), id: createId('incoming-file'),
transferId: payload.transfer_id, transferId: payload.transfer_id,
kind: 'file', kind: 'file',
name: payload.name || 'file', name: normalizeDisplayName(payload.name, 'file'),
size: formatFileSize(Number(payload.size_bytes || 0)), size: formatFileSize(Number(payload.size_bytes || 0)),
sizeBytes: Number(payload.size_bytes || 0), sizeBytes: Number(payload.size_bytes || 0),
status: '接收中...', status: '接收中...',
@@ -2010,7 +2060,7 @@ function handleIncomingTransferFile(envelope) {
id: createId('incoming-file'), id: createId('incoming-file'),
transferId: payload.transfer_id, transferId: payload.transfer_id,
kind: 'file', kind: 'file',
name: payload.name || 'file', name: normalizeDisplayName(payload.name, 'file'),
size: '', size: '',
sizeBytes: 0, sizeBytes: 0,
status: '可保存', status: '可保存',
@@ -2742,7 +2792,7 @@ handleIncomingTransferCreated = function handleIncomingTransferCreatedOverride(e
id: createId('incoming-file'), id: createId('incoming-file'),
transferId: payload.transfer_id, transferId: payload.transfer_id,
kind: 'file', kind: 'file',
name: payload.name || 'file', name: normalizeDisplayName(payload.name, 'file'),
size: formatFileSize(Number(payload.size_bytes || 0)), size: formatFileSize(Number(payload.size_bytes || 0)),
sizeBytes: Number(payload.size_bytes || 0), sizeBytes: Number(payload.size_bytes || 0),
status: '等待接收...', status: '等待接收...',
@@ -2791,7 +2841,7 @@ handleIncomingTransferFile = function handleIncomingTransferFileOverride(envelop
id: createId('incoming-file'), id: createId('incoming-file'),
transferId: payload.transfer_id, transferId: payload.transfer_id,
kind: 'file', kind: 'file',
name: payload.name || 'file', name: normalizeDisplayName(payload.name, 'file'),
size: '', size: '',
sizeBytes: 0, sizeBytes: 0,
status: '可保存', status: '可保存',