bun 多文件上传会有问题
This commit is contained in:
		| @@ -1,6 +1,6 @@ | ||||
| import path from 'path'; | ||||
| import fs from 'fs'; | ||||
| import { storage } from '../query.ts'; | ||||
| import { storage, baseURL } from '../query.ts'; | ||||
| import { chalk } from '../chalk.ts'; | ||||
|  | ||||
| type DownloadTask = { | ||||
| @@ -20,6 +20,40 @@ export type Package = { | ||||
|   key?: string; | ||||
|   [key: string]: any; | ||||
| }; | ||||
| type Options = { | ||||
|   check?: boolean; | ||||
|   returnContent?: boolean; | ||||
|   [key: string]: any; | ||||
| }; | ||||
| export const fetchLink = async (url: string, opts?: Options) => { | ||||
|   const token = process.env.KEVISUAL_TOKEN || storage.getItem('token'); | ||||
|   const fetchURL = new URL(url); | ||||
|   const check = opts?.check ?? false; | ||||
|   if (check) { | ||||
|     if (!url.startsWith(baseURL)) { | ||||
|       throw new Error('url must start with ' + baseURL); | ||||
|     } | ||||
|   } | ||||
|   if (token) { | ||||
|     fetchURL.searchParams.set('token', token); | ||||
|   } | ||||
|   fetchURL.searchParams.set('download', 'true'); | ||||
|   const res = await fetch(fetchURL.toString()); | ||||
|   const blob = await res.blob(); | ||||
|   const type = blob.type; | ||||
|   let content: Buffer | undefined; | ||||
|   if (opts?.returnContent) { | ||||
|     content = Buffer.from(await blob.arrayBuffer()); | ||||
|   } | ||||
|   const pathname = fetchURL.pathname; | ||||
|   const filename = pathname.split('/').pop(); | ||||
|   return { | ||||
|     filename, | ||||
|     blob, | ||||
|     type, | ||||
|     content, | ||||
|   }; | ||||
| }; | ||||
| type InstallAppOpts = { | ||||
|   appDir?: string; | ||||
|   kevisualUrl?: string; | ||||
| @@ -65,20 +99,12 @@ export const installApp = async (app: Package, opts: InstallAppOpts = {}) => { | ||||
|         fs.mkdirSync(dir, { recursive: true }); | ||||
|       } | ||||
|       console.log('downloadUrwl', downloadUrl); | ||||
|       const token = process.env.KEVISUAL_TOKEN || storage.getItem('token'); | ||||
|       const fetchURL = new URL(downloadUrl); | ||||
|       if (token) { | ||||
|         fetchURL.searchParams.set('token', token); | ||||
|       } | ||||
|       fetchURL.searchParams.set('download', 'true'); | ||||
|       const res = await fetch(fetchURL.toString()); | ||||
|       const blob = await res.blob(); | ||||
|       const type = blob.type; | ||||
|       const { blob, type } = await fetchLink(downloadUrl); | ||||
|       if (type.includes('text/html')) { | ||||
|         const html = await blob.text(); | ||||
|         if (html === 'fetchRes is error') { | ||||
|           console.log(chalk.red('fetchRes is error')); | ||||
|           break; | ||||
|           console.log(chalk.red('fetchRes is error'), '下载失败', downloadUrl); | ||||
|           throw new Error('fetchRes is error'); | ||||
|         } | ||||
|       } | ||||
|       fs.writeFileSync(downloadPath, Buffer.from(await blob.arrayBuffer())); | ||||
|   | ||||
							
								
								
									
										63
									
								
								src/module/download/upload.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/module/download/upload.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| import FormData from 'form-data'; | ||||
| export const handleResponse = async (err: any, res: any) => { | ||||
|   return new Promise((resolve) => { | ||||
|     if (err) { | ||||
|       console.error('Upload failed:', err); | ||||
|       resolve({ code: 500, message: err }); | ||||
|       return; | ||||
|     } | ||||
|     // 处理服务器响应 | ||||
|     let body = ''; | ||||
|     res.on('data', (chunk) => { | ||||
|       body += chunk; | ||||
|     }); | ||||
|     res.on('end', () => { | ||||
|       try { | ||||
|         const res = JSON.parse(body); | ||||
|         resolve(res); | ||||
|       } catch (e) { | ||||
|         resolve({ code: 500, message: body }); | ||||
|       } | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
| export const getFormParams = (opts: UploadOptions, headers: any): FormData.SubmitOptions => { | ||||
|   const url = new URL(opts.url); | ||||
|   if (opts.token) { | ||||
|     // url.searchParams.append('token', opts.token); | ||||
|   } | ||||
|   const value: FormData.SubmitOptions = { | ||||
|     path: url.pathname + url.search, | ||||
|     host: url.hostname, | ||||
|     method: 'POST', | ||||
|     protocol: url.protocol === 'https:' ? 'https:' : 'http:', | ||||
|     port: url.port || (url.protocol === 'https:' ? 443 : 80), | ||||
|     headers: { | ||||
|       Authorization: 'Bearer ' + opts.token, | ||||
|       ...headers, | ||||
|     }, | ||||
|   }; | ||||
|   return value; | ||||
| }; | ||||
| type UploadOptions = { | ||||
|   url: string | URL; | ||||
|   file?: string | Buffer | File; | ||||
|   token?: string; | ||||
|   form?: FormData; | ||||
| }; | ||||
| export const upload = (opts: UploadOptions): Promise<{ code?: number; message?: string; [key: string]: any }> => { | ||||
|   const form = opts?.form || new FormData(); | ||||
|   if (!opts.form) { | ||||
|     if (typeof opts.file === 'string') { | ||||
|       form.append('file', Buffer.from(opts.file)); | ||||
|     } else { | ||||
|       form.append('file', opts.file); | ||||
|     } | ||||
|   } | ||||
|   const headers = form.getHeaders(); | ||||
|   return new Promise((resolve) => { | ||||
|     form.submit(getFormParams(opts, headers), (err, res) => { | ||||
|       handleResponse(err, res).then(resolve); | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user