修复安卓手机显示名称不符显示为linux的问题;修复文件名乱码的问题
This commit is contained in:
@@ -456,6 +456,7 @@ func (h *HTTPHandler) downloadFallback(c *gin.Context) {
|
||||
defer cancel()
|
||||
|
||||
filename := filepath.Base(transfer.Name)
|
||||
filename = decodeDownloadFilename(filename)
|
||||
if filename == "." || filename == "" {
|
||||
filename = "download.bin"
|
||||
}
|
||||
@@ -597,6 +598,19 @@ func contentDisposition(filename string) string {
|
||||
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 {
|
||||
if h.deps.MinIOClient == nil {
|
||||
return nil
|
||||
|
||||
17
frontend/dist/assets/index-BoiTbES-.js
vendored
Normal file
17
frontend/dist/assets/index-BoiTbES-.js
vendored
Normal file
File diff suppressed because one or more lines are too long
17
frontend/dist/assets/index-DPzeYqvr.js
vendored
17
frontend/dist/assets/index-DPzeYqvr.js
vendored
File diff suppressed because one or more lines are too long
2
frontend/dist/index.html
vendored
2
frontend/dist/index.html
vendored
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<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">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -302,6 +302,7 @@ async function loadPendingDownloads() {
|
||||
const downloads = await devicesApi.listPendingDownloads(localDevice.value.id)
|
||||
pendingDownloads.value = downloads.map((item) => ({
|
||||
...item,
|
||||
name: normalizeDisplayName(item.name),
|
||||
download_path: item.download_path || `/api/transfers/${encodeURIComponent(item.transfer_id)}/fallback/download`,
|
||||
size_label: formatFileSize(Number(item.size_bytes || 0)),
|
||||
created_label: formatRelativeTime(item.created_at),
|
||||
@@ -551,7 +552,7 @@ function addFiles(files) {
|
||||
id: createId(`file-${index}`),
|
||||
kind: 'file',
|
||||
file,
|
||||
name: file.name,
|
||||
name: normalizeDisplayName(file.name),
|
||||
size: formatFileSize(file.size),
|
||||
sizeBytes: file.size,
|
||||
status: '待发送',
|
||||
@@ -1166,15 +1167,47 @@ function ensureDeviceId() {
|
||||
|
||||
function ensureDeviceName(deviceId) {
|
||||
let deviceName = localStorage.getItem(DEVICE_NAME_KEY)
|
||||
if (!deviceName) {
|
||||
const platform = navigator.userAgentData?.platform || navigator.platform || 'Web'
|
||||
deviceName = `${platform} ${deviceId.slice(0, 4)}`
|
||||
if (!deviceName || isLegacyAutoDeviceName(deviceName, deviceId)) {
|
||||
deviceName = `${detectDeviceLabel()} ${deviceId.slice(0, 4)}`
|
||||
localStorage.setItem(DEVICE_NAME_KEY, 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() {
|
||||
const source = `${navigator.userAgent} ${navigator.platform}`.toLowerCase()
|
||||
if (source.includes('iphone') || source.includes('android') || source.includes('mobile')) {
|
||||
@@ -1186,6 +1219,23 @@ function detectDeviceType() {
|
||||
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) {
|
||||
if (type === 'phone') {
|
||||
return 'smartphone'
|
||||
@@ -1600,7 +1650,7 @@ function handleIncomingRealtimeFileMeta(payload) {
|
||||
ensurePeerSession(sender, true)
|
||||
|
||||
incomingFileBuffers.set(payload.transfer_id, {
|
||||
name: payload.name || 'file',
|
||||
name: normalizeDisplayName(payload.name, 'file'),
|
||||
mimeType: payload.mime_type || 'application/octet-stream',
|
||||
sizeBytes: Number(payload.size_bytes || 0),
|
||||
receivedBytes: 0,
|
||||
@@ -1613,7 +1663,7 @@ function handleIncomingRealtimeFileMeta(payload) {
|
||||
id: createId('incoming-file'),
|
||||
transferId: payload.transfer_id,
|
||||
kind: 'file',
|
||||
name: payload.name || 'file',
|
||||
name: normalizeDisplayName(payload.name, 'file'),
|
||||
size: formatFileSize(Number(payload.size_bytes || 0)),
|
||||
sizeBytes: Number(payload.size_bytes || 0),
|
||||
status: '正在接收...',
|
||||
@@ -1965,7 +2015,7 @@ function handleIncomingTransferCreated(envelope) {
|
||||
id: createId('incoming-file'),
|
||||
transferId: payload.transfer_id,
|
||||
kind: 'file',
|
||||
name: payload.name || 'file',
|
||||
name: normalizeDisplayName(payload.name, 'file'),
|
||||
size: formatFileSize(Number(payload.size_bytes || 0)),
|
||||
sizeBytes: Number(payload.size_bytes || 0),
|
||||
status: '接收中...',
|
||||
@@ -2010,7 +2060,7 @@ function handleIncomingTransferFile(envelope) {
|
||||
id: createId('incoming-file'),
|
||||
transferId: payload.transfer_id,
|
||||
kind: 'file',
|
||||
name: payload.name || 'file',
|
||||
name: normalizeDisplayName(payload.name, 'file'),
|
||||
size: '',
|
||||
sizeBytes: 0,
|
||||
status: '可保存',
|
||||
@@ -2742,7 +2792,7 @@ handleIncomingTransferCreated = function handleIncomingTransferCreatedOverride(e
|
||||
id: createId('incoming-file'),
|
||||
transferId: payload.transfer_id,
|
||||
kind: 'file',
|
||||
name: payload.name || 'file',
|
||||
name: normalizeDisplayName(payload.name, 'file'),
|
||||
size: formatFileSize(Number(payload.size_bytes || 0)),
|
||||
sizeBytes: Number(payload.size_bytes || 0),
|
||||
status: '等待接收...',
|
||||
@@ -2791,7 +2841,7 @@ handleIncomingTransferFile = function handleIncomingTransferFileOverride(envelop
|
||||
id: createId('incoming-file'),
|
||||
transferId: payload.transfer_id,
|
||||
kind: 'file',
|
||||
name: payload.name || 'file',
|
||||
name: normalizeDisplayName(payload.name, 'file'),
|
||||
size: '',
|
||||
sizeBytes: 0,
|
||||
status: '可保存',
|
||||
|
||||
Reference in New Issue
Block a user