diff --git a/src/core/openlist/openlist.service.ts b/src/core/openlist/openlist.service.ts index 20a2659..82e5ebe 100644 --- a/src/core/openlist/openlist.service.ts +++ b/src/core/openlist/openlist.service.ts @@ -1,6 +1,6 @@ import { Inject, Injectable, Logger } from '@nestjs/common'; import { AppConfigService } from '../../config/config.service'; -import { DirectoryList, FileInfo, UserInfo } from './openlist.types'; +import { FileInfo, FsList } from './openlist.types'; import { OpenListUtils } from './openlist.utils'; import * as moment from 'moment'; @@ -64,29 +64,12 @@ export class OpenListService { } } - /** - * 获取当前用户信息 - * @returns 用户信息 - */ - public async getUserInfo(): Promise { - try { - const token = await this.fetchToken( - this.configService.get('OPENLIST_API_BASE_USERNAME'), - this.configService.get('OPENLIST_API_BASE_PASSWORD'), - ); - return await OpenListUtils.getUserInfo(token); - } catch (error) { - this.logger.error('获取用户信息失败:', error); - throw new Error('获取用户信息失败'); - } - } - /** * 列出目录下的所有文件 * @param path 目录路径 * @returns 目录下的文件列表 */ - public async listFiles(path: string): Promise { + public async listFiles(path: string): Promise { try { const token = await this.fetchToken( this.configService.get('OPENLIST_API_BASE_USERNAME'), @@ -142,14 +125,19 @@ export class OpenListService { * 上传文件 * @param filePath 上传路径 * @param file 文件 + * @param filePathOnserver 服务器路径 */ - public async uploadFile(filePath: string, file: any): Promise { + public async uploadFile( + filePath: string, + file: any, + filePathOnserver: string, + ): Promise { try { const token = await this.fetchToken( this.configService.get('OPENLIST_API_BASE_USERNAME'), this.configService.get('OPENLIST_API_BASE_PASSWORD'), ); - await OpenListUtils.uploadFile(token, filePath, file); + await OpenListUtils.uploadFile(token, filePath, filePathOnserver, file); } catch (error) { this.logger.error('上传文件失败:', error); throw new Error('上传文件失败'); diff --git a/src/core/openlist/openlist.types.ts b/src/core/openlist/openlist.types.ts index 6b695c4..60ca161 100644 --- a/src/core/openlist/openlist.types.ts +++ b/src/core/openlist/openlist.types.ts @@ -1,25 +1,63 @@ -export interface UserInfo { - id: number; - username: string; - email: string; - role: string; - created_at: string; - updated_at: string; -} - -export interface DirectoryList { - path: string; - name: string; - is_directory: boolean; - size: number; - modified_at: string; +/** + * /api/fs/list 文件目录列表 + */ +export interface FsList { + code: number; + message: string; + data: { + content: [ + name: string, + size: number, + is_dir: boolean, + modified: string, //修改时间 + sign: string, //签名 + thumb: string, //略缩图 + type: number, //类型 + ]; + total: number; //总数 + readme: string; //说明? + write: boolean; //是否可写入 + provider: string; + header: string; + }; } +/** + * /api/fs/get 获取文件/目录信息 + */ export interface FileInfo { - path: string; - size: number; - mime_type: string; - created_at: string; - modified_at: string; - is_directory: boolean; + code: number; + message: string; + data: { + name: string; + size: number; + is_dir: boolean; + modified: string; + sign: string; + thumb: string; + type: number; + raw_url: string; //原始url + readme: string; + provider: string; + created: string; //创建时间 + header: string; + }; +} + +/** + * /api/fs/put 流式上传文件 + */ +export interface FileUpload { + code: number; + message: string; + data: { + task: { + id: string; + name: string; + state: number; + status: string; + progress: number; + error: string; + }; + }; } diff --git a/src/core/openlist/openlist.utils.ts b/src/core/openlist/openlist.utils.ts index 4a69977..1893cf7 100644 --- a/src/core/openlist/openlist.utils.ts +++ b/src/core/openlist/openlist.utils.ts @@ -1,8 +1,8 @@ import axios from 'axios'; import { AppConfigService } from '../../config/config.service'; import { Inject, Logger } from '@nestjs/common'; -import * as crypto from 'crypto'; import * as fs from 'fs'; +import { FileInfo, FileUpload, FsList } from './openlist.types'; export class OpenListUtils { private static readonly logger = new Logger(OpenListUtils.name); @@ -27,10 +27,10 @@ export class OpenListUtils { username: username, password: password, }); - this.logger.debug(response); + //this.logger.debug(response); if (response.data.data.token) { const token: string = response.data.data.token; - this.logger.log(`获取Token成功: ${token}`); + this.logger.debug(`获取Token成功: ${token}`); return token; } else { this.logger.error(`获取Token失败: ${response.data.data.message}`); @@ -42,45 +42,23 @@ export class OpenListUtils { } } - /** - * 获取当前用户信息 - * @param token 用户 Token - * @returns 用户信息 - */ - static async getUserInfo(token: string): Promise { - const url = `${this.apiBaseUrl}/auth/userinfo`; - - try { - const response = await axios.get(url, { - headers: { Authorization: `Bearer ${token}` }, - }); - this.logger.log('获取用户信息成功..'); - return response.data; - } catch (error) { - this.logger.error('获取用户信息失败..', error); - throw new Error('获取用户信息失败..'); - } - } - /** * 获取目录列表 * @param token 用户 Token * @param path 目录路径 - * @returns 文件目录列表 */ - static async listDirectory(token: string, path: string): Promise { - const url = `${this.apiBaseUrl}/fs/list`; - + static async listDirectory(token: string, path: string): Promise { + const url = `${this.apiBaseUrl}/api/fs/list`; try { const response = await axios.get(url, { params: { path }, headers: { Authorization: `Bearer ${token}` }, }); - this.logger.log('列出目录成功..'); + this.logger.log(`列出目录${path}成功..`); return response.data; } catch (error) { - this.logger.error('列出目录失败..', error); - throw new Error('列出目录失败..'); + this.logger.error(`列出目录${path}失败..`, error); + throw new Error(`列出目录${path}失败..`); } } @@ -88,11 +66,9 @@ export class OpenListUtils { * 获取某个文件的详细信息 * @param token 用户 Token * @param filePath 文件路径 - * @returns 文件信息 */ - static async getFileInfo(token: string, filePath: string): Promise { + static async getFileInfo(token: string, filePath: string): Promise { const url = `${this.apiBaseUrl}/fs/info`; - try { const response = await axios.get(url, { params: { path: filePath }, @@ -106,36 +82,6 @@ export class OpenListUtils { } } - /** - * 文件重命名 - * @param token 用户 Token - * @param oldPath 旧路径 - * @param newPath 新路径 - * @returns 重命名结果 - */ - static async renameFile( - token: string, - oldPath: string, - newPath: string, - ): Promise { - const url = `${this.apiBaseUrl}/fs/rename`; - - try { - const response = await axios.post( - url, - { oldPath, newPath }, - { - headers: { Authorization: `Bearer ${token}` }, - }, - ); - this.logger.log(`文件重命名成功: ${oldPath} => ${newPath}`); - return response.data; - } catch (error) { - this.logger.error('文件重命名失败..', error); - throw new Error('文件重命名失败..'); - } - } - /** * 下载文件 * @param token 用户 Token @@ -147,24 +93,24 @@ export class OpenListUtils { filePath: string, downloadPath: string, ): Promise { - const url = `${this.apiBaseUrl}/fs/download`; - try { - const response = await axios.get(url, { - params: { path: filePath }, - headers: { Authorization: `Bearer ${token}` }, + const fileInfo = await this.getFileInfo(token, filePath); + const rawUrl = fileInfo.data.raw_url; + if (!rawUrl) { + this.logger.error('文件没有找到 raw_url 地址..'); + throw new Error('文件没有找到 raw_url 地址..'); + } + const response = await axios.get(rawUrl, { responseType: 'stream', }); const writer = fs.createWriteStream(downloadPath); response.data.pipe(writer); - writer.on('finish', () => { this.logger.log(`文件下载成功: ${downloadPath}`); }); - writer.on('error', (error) => { this.logger.error('下载文件失败', error); - throw new Error('下载文件失败'); + throw new Error('下载文件失败..'); }); } catch (error) { this.logger.error('下载文件失败..', error); @@ -173,68 +119,39 @@ export class OpenListUtils { } /** - * 上传文件 + * 流式上传文件 * @param token 用户 Token * @param filePath 上传文件的路径 - * @param file 上传文件的内容 - * @returns 上传结果 + * @param filePathOnServer 服务器上保存的文件路径 + * @param file 文件流 */ static async uploadFile( token: string, filePath: string, - file: any, - ): Promise { - const url = `${this.apiBaseUrl}/fs/upload`; - - const formData = new FormData(); - formData.append('file', file); - formData.append('path', filePath); + filePathOnServer: string, + file: fs.ReadStream, + ): Promise { + const url = `${this.apiBaseUrl}/api/fs/put`; + const headers = { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/octet-stream', + 'Content-Length': file.bytesRead, + 'File-Path': encodeURIComponent(filePathOnServer), + }; try { - const response = await axios.post(url, formData, { - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'multipart/form-data', + const response = await axios.put(url, file, { + headers, + params: { + path: filePath, + 'As-Task': 'true', //作为任务 }, }); - - this.logger.log(`文件上传成功: ${filePath}`); + this.logger.log(`文件上传成功: ${filePathOnServer}`); return response.data; } catch (error) { this.logger.error('上传文件失败..', error); throw new Error('上传文件失败..'); } } - - /** - * 获取某个目录下的所有文件 - * @param token 用户 Token - * @param directoryPath 目录路径 - * @returns 文件列表 - */ - static async listFilesInDirectory( - token: string, - directoryPath: string, - ): Promise { - const directoryInfo = await this.listDirectory(token, directoryPath); - return directoryInfo.filter( - (item: { is_directory: any }) => !item.is_directory, - ); - } - - /** - * 检查文件更新 - * @param token 用户 Token - * @param filePath 文件路径 - * @param lastModified 上次改动时间 - * @returns 文件是否更新 - */ - static async checkFileUpdate( - token: string, - filePath: string, - lastModified: string, - ): Promise { - const fileInfo = await this.getFileInfo(token, filePath); - return fileInfo.modified_at !== lastModified; - } }