import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory' import { getOption, getResponse, miaoFetchConfig, deleteOption, uploadOption, queryOption, renameOption, cutOption, mkdirOption, getFileOption } from '@/types/fetch' import Config from '@/config' import axios, { AxiosRequestConfig, AxiosResponse } from 'axios' export const useMiaoFetch = (option?: miaoFetchConfig) => { const retry = option?.retry ?? 0 const controller = new AbortController() let flag = true return { miaoFetch: async ( config: AxiosRequestConfig ): Promise> => { let counter = 0 let response: any let errList = [] while (flag && counter <= retry) { try { response = await axios({ ...config, signal: controller.signal }) return response } catch (_e) { errList.push(_e) counter += 1 } } throw errList }, /** * 强制终止miaoFetch */ abortMiaoFetch: () => { flag = false controller.abort() } } } const miaoFetchApi = { /** * 获取对应文件夹下的数据 */ async get( vDirectory: VirtualDirectory, option?: getOption ): Promise { const { baseUrl, api } = Config const url = `${baseUrl}${api.get}${vDirectory.path}` const retry = option?.retry ?? 0 const { miaoFetch } = useMiaoFetch({ retry }) const response = await miaoFetch({ url }) return response.data }, /** * 获取对应文件下的数据 */ getFile(vFile: VirtualFile, option?: getFileOption) { // const { baseUrl, api } = Config const url = vFile.url const retry = option?.retry ?? 0 const axiosOption = option?.axiosOption ?? {} const { miaoFetch, abortMiaoFetch: abort } = useMiaoFetch({ retry }) const response = miaoFetch({ url, responseType: 'arraybuffer', onDownloadProgress(progressEvent) { option && option.onProcess && option.onProcess( progressEvent.total ? progressEvent.loaded / progressEvent.total : -1 ) }, ...axiosOption }) return { response: new Promise(async (resolve) => { resolve(new Uint8Array((await response).data)) }), abort } }, /** * 上传单个文件到对应文件夹, 后续要将data类型改成buffer以支持分片上传 * 正常上传文件请使用uploadQueue */ upload(data: File, targetVDir: VirtualDirectory, option?: uploadOption) { const { baseUrl, api } = Config const url = `${baseUrl}${api.upload}${targetVDir.path}` const retry = option?.retry ?? 0 const { miaoFetch, abortMiaoFetch } = useMiaoFetch({ retry }) const sizeTotal = data.size const opType = option?.type ?? 'write' const formData = new FormData() formData.append('file', data) // 必须这样传,不然中文乱码 formData.append('fileName', data.name) formData.append('operateType', opType) return { abort: () => abortMiaoFetch(), response: new Promise<{ message: 'success' | 'failed' error?: string }>(async (resolve) => { const response = await miaoFetch({ url, method: 'post', data: formData, onUploadProgress(progressEvent) { option && option.onProcess && option.onProcess(progressEvent.loaded / sizeTotal) } }) resolve(response.data) }) } }, /** * 在目标文件夹下创建新的文件夹 */ mkdir( targetVDir: VirtualDirectory, newFolderName: string, option?: mkdirOption ) { const { baseUrl, api } = Config const url = `${baseUrl}${api.mkdir}${targetVDir.path}` const { miaoFetch } = useMiaoFetch({ retry: option?.retry ?? 0 }) return new Promise<{ message: 'success' | 'failed' error?: string }>(async (resolve) => { const response = await miaoFetch({ url, method: 'post', data: { folderName: newFolderName } }) resolve(response.data) }) }, /** * 在目标文件夹下创建新的空文件,实际上是通过upload空文件实现 */ mkFile( targetVDir: VirtualDirectory, newFileName: string, option?: uploadOption ) { const emptyBlob = new Blob([]) const emptyFile = new File([emptyBlob], newFileName, { type: 'text/plain' }) return this.upload(emptyFile, targetVDir, option) }, /** * 删除对应的文件或文件夹,若为文件夹会递归删除 */ delete(target: VirtualFile | VirtualDirectory, option?: deleteOption) { const { baseUrl, api } = Config const url = `${baseUrl}${api.delete}${target.path}` const retry = option?.retry ?? 0 const { miaoFetch } = useMiaoFetch({ retry }) return { response: new Promise<{ eventId: number }>(async (resolve) => { const response = await miaoFetch({ url, method: 'post' }) resolve(response.data) }) } }, /** * 重命名对应的文件或文件夹 */ rename( target: VirtualFile | VirtualDirectory, newName: string, option?: renameOption ) { const { baseUrl, api } = Config const url = `${baseUrl}${api.rename}${target.path}` const retry = option?.retry ?? 0 const { miaoFetch } = useMiaoFetch({ retry }) return { response: new Promise<{ eventId: number }>(async (resolve) => { const response = await miaoFetch({ url, method: 'post', data: { newName } }) resolve(response.data) }) } }, /** * 剪切文件或文件夹 */ cut( target: VirtualFile | VirtualDirectory, to: VirtualDirectory, option?: cutOption ) { const newPath = to.path const { baseUrl, api } = Config const url = `${baseUrl}${api.cut}${target.path}` const retry = option?.retry ?? 0 const { miaoFetch } = useMiaoFetch({ retry }) return { response: new Promise<{ eventId: number }>(async (resolve) => { const response = await miaoFetch({ url, method: 'post', data: { newPath } }) resolve(response.data) }) } }, /** * 查询服务端操作事件的进展 */ query(eventId: number, option?: queryOption) { const { baseUrl, api } = Config const url = `${baseUrl}${api.query}` const retry = option?.retry ?? 0 const { miaoFetch } = useMiaoFetch({ retry }) return { response: new Promise<{ status: 'process' | 'success' | 'failed' error?: unknown }>(async (resolve) => { const response = await miaoFetch({ url, method: 'get', params: { id: eventId } }) resolve(response.data) }) } } } export default function useMiaoFetchApi() { return miaoFetchApi }