@kevisual/api 0.0.38 → 0.0.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/query/query-resources/index.ts +45 -14
package/package.json
CHANGED
|
@@ -62,7 +62,7 @@ export class QueryResources {
|
|
|
62
62
|
const url = `${this.prefix}${filepath}`;
|
|
63
63
|
return this.get({}, { url, method: 'GET', ...opts, headers: this.header(opts?.headers, false), isText: true });
|
|
64
64
|
}
|
|
65
|
-
async uploadFile(filepath: string, content: string | Blob, opts?: DataOpts): Promise<Result<any>> {
|
|
65
|
+
async uploadFile(filepath: string, content: string | Blob, opts?: DataOpts & { chunkSize?: number, maxSize?: number }): Promise<Result<any>> {
|
|
66
66
|
const pathname = `${this.prefix}${filepath}`;
|
|
67
67
|
const filename = path.basename(pathname);
|
|
68
68
|
const type = getContentType(filename);
|
|
@@ -71,15 +71,15 @@ export class QueryResources {
|
|
|
71
71
|
// Blob 类型时 hashContent 返回 Promise
|
|
72
72
|
const hash = hashResult instanceof Promise ? await hashResult : hashResult;
|
|
73
73
|
url.searchParams.set('hash', hash);
|
|
74
|
-
|
|
74
|
+
const { chunkSize, maxSize, ...restOpts } = opts || {};
|
|
75
75
|
// 判断是否需要分块上传(文件大于20MB)
|
|
76
76
|
const isBlob = content instanceof Blob;
|
|
77
77
|
const fileSize = isBlob ? content.size : new Blob([content]).size;
|
|
78
|
-
const CHUNK_THRESHOLD = 20 * 1024 * 1024; // 20MB
|
|
78
|
+
const CHUNK_THRESHOLD = maxSize ?? 20 * 1024 * 1024; // 20MB
|
|
79
79
|
|
|
80
80
|
if (fileSize > CHUNK_THRESHOLD && isBlob) {
|
|
81
81
|
// 使用分块上传
|
|
82
|
-
return this.uploadChunkedFile(filepath, content, hash,
|
|
82
|
+
return this.uploadChunkedFile(filepath, content, hash, { chunkSize, ...restOpts });
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
const formData = new FormData();
|
|
@@ -94,15 +94,15 @@ export class QueryResources {
|
|
|
94
94
|
method: 'POST',
|
|
95
95
|
body: formData,
|
|
96
96
|
timeout: 5 * 60 * 1000, // 5分钟超时
|
|
97
|
-
...
|
|
98
|
-
headers: { ...
|
|
97
|
+
...restOpts,
|
|
98
|
+
headers: { ...restOpts?.headers, ...this.header(restOpts?.headers, false) },
|
|
99
99
|
params: {
|
|
100
100
|
hash: hash,
|
|
101
|
-
...
|
|
101
|
+
...restOpts?.params,
|
|
102
102
|
},
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
|
-
async uploadChunkedFile(filepath: string, file: Blob, hash: string, opts?: DataOpts): Promise<Result<any>> {
|
|
105
|
+
async uploadChunkedFile(filepath: string, file: Blob, hash: string, opts?: DataOpts & { chunkSize?: number }): Promise<Result<any>> {
|
|
106
106
|
const pathname = `${this.prefix}${filepath}`;
|
|
107
107
|
const filename = path.basename(pathname);
|
|
108
108
|
const url = new URL(pathname, window.location.origin);
|
|
@@ -111,8 +111,8 @@ export class QueryResources {
|
|
|
111
111
|
console.log(`url,`, url, hash);
|
|
112
112
|
// 预留 eventSource 支持(暂不处理)
|
|
113
113
|
// const createEventSource = opts?.createEventSource;
|
|
114
|
-
|
|
115
|
-
const chunkSize = 5 * 1024 * 1024; // 5MB
|
|
114
|
+
const { chunkSize: _chunkSize, ...restOpts } = opts || {};
|
|
115
|
+
const chunkSize = _chunkSize ?? 5 * 1024 * 1024; // 5MB
|
|
116
116
|
const totalChunks = Math.ceil(file.size / chunkSize);
|
|
117
117
|
|
|
118
118
|
for (let currentChunk = 0; currentChunk < totalChunks; currentChunk++) {
|
|
@@ -134,23 +134,40 @@ export class QueryResources {
|
|
|
134
134
|
method: 'POST',
|
|
135
135
|
body: formData,
|
|
136
136
|
timeout: 5 * 60 * 1000, // 5分钟超时
|
|
137
|
-
...
|
|
138
|
-
headers: { ...
|
|
137
|
+
...restOpts,
|
|
138
|
+
headers: { ...restOpts?.headers, ...this.header(restOpts?.headers, false) },
|
|
139
139
|
params: {
|
|
140
140
|
hash: hash,
|
|
141
141
|
chunk: '1',
|
|
142
|
-
|
|
142
|
+
chunkIndex: currentChunk,
|
|
143
|
+
totalChunks,
|
|
144
|
+
...restOpts?.params,
|
|
143
145
|
},
|
|
144
146
|
});
|
|
147
|
+
if (res.code !== 200) {
|
|
148
|
+
throw new Error(`Chunk upload failed with code ${res!.code}, message: ${res!.message}`);
|
|
149
|
+
}
|
|
145
150
|
console.log(`Chunk ${currentChunk + 1}/${totalChunks} uploaded`, res);
|
|
146
151
|
} catch (error) {
|
|
147
152
|
console.error(`Error uploading chunk ${currentChunk + 1}/${totalChunks}`, error);
|
|
148
|
-
|
|
153
|
+
return { code: 500, message: `分块上传失败: ${(error as Error).message}` };
|
|
149
154
|
}
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
return { code: 200, message: '上传成功' };
|
|
153
158
|
}
|
|
159
|
+
|
|
160
|
+
async getState(filepath: string, opts?: DataOpts): Promise<Result<Stat>> {
|
|
161
|
+
const url = `${this.prefix}${filepath}`;
|
|
162
|
+
return adapter({
|
|
163
|
+
url,
|
|
164
|
+
params: {
|
|
165
|
+
stat: '1',
|
|
166
|
+
},
|
|
167
|
+
method: 'GET' as any,
|
|
168
|
+
headers: this.header(opts?.headers),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
154
171
|
async createFolder(folderpath: string, opts?: DataOpts): Promise<Result<any>> {
|
|
155
172
|
const filepath = folderpath.endsWith('/') ? `${folderpath}keep.txt` : `${folderpath}/keep.txt`;
|
|
156
173
|
return this.uploadFile(filepath, '文件夹占位,其他文件不存在,文件夹不存在,如果有其他文件夹,删除当前文件夹占位文件即可', opts);
|
|
@@ -247,3 +264,17 @@ export const getContentType = (filename: string): string => {
|
|
|
247
264
|
|
|
248
265
|
return type;
|
|
249
266
|
};
|
|
267
|
+
|
|
268
|
+
type Stat = {
|
|
269
|
+
"standardHeaders": any,
|
|
270
|
+
"size": string,
|
|
271
|
+
"etag": string,
|
|
272
|
+
"lastModified": string,
|
|
273
|
+
"metaData": {
|
|
274
|
+
"app-source": string,
|
|
275
|
+
"cache-control": string,
|
|
276
|
+
"content-type": string,
|
|
277
|
+
"share"?: string
|
|
278
|
+
},
|
|
279
|
+
"versionId": null
|
|
280
|
+
}
|