Skip to content

Commit 18de86a

Browse files
committed
fix import file size limit to 20mb
1 parent cbb8ee8 commit 18de86a

6 files changed

Lines changed: 33 additions & 9 deletions

File tree

admin/handler.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"fmt"
1414
"io"
1515
"log"
16+
"mime/multipart"
1617
"net"
1718
"net/http"
1819
"reflect"
@@ -75,6 +76,8 @@ const (
7576
adminAPIKeyCountNamespace = "api-key-count"
7677
adminUsageStatsCacheTTL = 5 * time.Second
7778
adminChartCacheTTL = 10 * time.Second
79+
importFileSizeLimitBytes = 20 * 1024 * 1024
80+
importFileSizeLimitLabel = "20MB"
7881
)
7982

8083
func (h *Handler) getRuntimeJSON(ctx context.Context, namespace, key string, dest interface{}) bool {
@@ -110,6 +113,13 @@ func (h *Handler) setRuntimeJSON(ctx context.Context, namespace, key string, val
110113
}
111114
}
112115

116+
func validateImportFileSize(fh *multipart.FileHeader) error {
117+
if fh.Size > importFileSizeLimitBytes {
118+
return fmt.Errorf("文件 %s 大小超过 %s", fh.Filename, importFileSizeLimitLabel)
119+
}
120+
return nil
121+
}
122+
113123
func (h *Handler) deleteRuntimeCache(ctx context.Context, namespace, key string) {
114124
if h == nil || h.cache == nil {
115125
return
@@ -1832,8 +1842,8 @@ func readUploadedImportFiles(c *gin.Context) ([]uploadedImportFile, error) {
18321842

18331843
result := make([]uploadedImportFile, 0, len(files))
18341844
for _, fh := range files {
1835-
if fh.Size > 2*1024*1024 {
1836-
return nil, fmt.Errorf("文件 %s 大小超过 2MB", fh.Filename)
1845+
if err := validateImportFileSize(fh); err != nil {
1846+
return nil, err
18371847
}
18381848

18391849
f, err := fh.Open()
@@ -1905,8 +1915,8 @@ func (h *Handler) importAccountsJSON(c *gin.Context, proxyURL string) {
19051915
var allTokens []importToken
19061916

19071917
for _, fh := range files {
1908-
if fh.Size > 2*1024*1024 {
1909-
writeError(c, http.StatusBadRequest, fmt.Sprintf("文件 %s 大小超过 2MB", fh.Filename))
1918+
if err := validateImportFileSize(fh); err != nil {
1919+
writeError(c, http.StatusBadRequest, err.Error())
19101920
return
19111921
}
19121922

admin/import_json_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,20 @@ func TestReadUploadedImportFilesReadsRepeatedFileFields(t *testing.T) {
298298
}
299299
}
300300

301+
func TestValidateImportFileSize(t *testing.T) {
302+
if err := validateImportFileSize(&multipart.FileHeader{Filename: "ok.txt", Size: importFileSizeLimitBytes}); err != nil {
303+
t.Fatalf("validateImportFileSize returned error for boundary size: %v", err)
304+
}
305+
306+
err := validateImportFileSize(&multipart.FileHeader{Filename: "too-big.txt", Size: importFileSizeLimitBytes + 1})
307+
if err == nil {
308+
t.Fatal("expected oversized file error, got nil")
309+
}
310+
if got, want := err.Error(), "文件 too-big.txt 大小超过 20MB"; got != want {
311+
t.Fatalf("error = %q, want %q", got, want)
312+
}
313+
}
314+
301315
func TestImportAccountsJSONReturnsExistingNoTokenMessageForUnsupportedJSON(t *testing.T) {
302316
gin.SetMode(gin.TestMode)
303317

docs/API.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ curl -X POST http://localhost:8080/api/admin/accounts/at \
642642

643643
| 字段 | 类型 | 必填 | 说明 |
644644
| --------- | ------ | ---- | ----------------------------------------- |
645-
| file | file || 上传文件(最大 2MB,JSON 格式支持多文件) |
645+
| file | file || 上传文件(最大 20MB,JSON 格式支持多文件) |
646646
| format | string || 文件格式:`txt`(默认)、`json``at_txt` |
647647
| proxy_url | string || 代理 URL |
648648

frontend/src/locales/en.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,7 @@
14301430
},
14311431
"importAccounts": {
14321432
"title": "Import Accounts (File Upload)",
1433-
"desc": "Batch import accounts via file upload. Supports three formats: txt (one RT per line), json (CLIProxyAPI credential export compatible), at_txt (one AT per line). Max file size 2MB."
1433+
"desc": "Batch import accounts via file upload. Supports three formats: txt (one RT per line), json (CLIProxyAPI credential export compatible), at_txt (one AT per line). Max file size 20MB."
14341434
},
14351435
"deleteAccount": {
14361436
"title": "Delete Account",

frontend/src/locales/zh.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,7 @@
14301430
},
14311431
"importAccounts": {
14321432
"title": "Import Accounts (File Upload)",
1433-
"desc": "通过文件上传批量导入账号。支持三种格式:txt(每行一个 RT)、json(兼容 CLIProxyAPI 凭证导出)、at_txt(每行一个 AT)。文件大小限制 2MB"
1433+
"desc": "通过文件上传批量导入账号。支持三种格式:txt(每行一个 RT)、json(兼容 CLIProxyAPI 凭证导出)、at_txt(每行一个 AT)。文件大小限制 20MB"
14341434
},
14351435
"deleteAccount": {
14361436
"title": "Delete Account",

frontend/src/pages/docs/docsContent.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,8 @@ export function buildAdminSpecs(
441441
title: copy(locale, "文件批量导入账号", "Bulk import accounts from file"),
442442
description: copy(
443443
locale,
444-
"通过文件批量导入账号,支持 txt、CLIProxyAPI 导出的 json、以及每行一个 AT 的 at_txt,文件最大 2MB。",
445-
"Bulk import accounts from file. Supports txt, CLIProxyAPI-exported json, and at_txt with one access token per line; max file size is 2MB.",
444+
"通过文件批量导入账号,支持 txt、CLIProxyAPI 导出的 json、以及每行一个 AT 的 at_txt,文件最大 20MB。",
445+
"Bulk import accounts from file. Supports txt, CLIProxyAPI-exported json, and at_txt with one access token per line; max file size is 20MB.",
446446
),
447447
curl: `# TXT — one Refresh Token per line
448448
curl --request POST \\

0 commit comments

Comments
 (0)