feat:oplist上传下载文件实现

This commit is contained in:
Jerry 2025-09-15 18:40:31 +08:00
parent fcd50a2569
commit 4310e94547
3 changed files with 104 additions and 161 deletions

View File

@ -1,6 +1,6 @@
import { Inject, Injectable, Logger } from '@nestjs/common'; import { Inject, Injectable, Logger } from '@nestjs/common';
import { AppConfigService } from '../../config/config.service'; 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 { OpenListUtils } from './openlist.utils';
import * as moment from 'moment'; import * as moment from 'moment';
@ -64,29 +64,12 @@ export class OpenListService {
} }
} }
/**
*
* @returns
*/
public async getUserInfo(): Promise<UserInfo> {
try {
const token = await this.fetchToken(
<string>this.configService.get('OPENLIST_API_BASE_USERNAME'),
<string>this.configService.get('OPENLIST_API_BASE_PASSWORD'),
);
return await OpenListUtils.getUserInfo(token);
} catch (error) {
this.logger.error('获取用户信息失败:', error);
throw new Error('获取用户信息失败');
}
}
/** /**
* *
* @param path * @param path
* @returns * @returns
*/ */
public async listFiles(path: string): Promise<DirectoryList[]> { public async listFiles(path: string): Promise<FsList> {
try { try {
const token = await this.fetchToken( const token = await this.fetchToken(
<string>this.configService.get('OPENLIST_API_BASE_USERNAME'), <string>this.configService.get('OPENLIST_API_BASE_USERNAME'),
@ -142,14 +125,19 @@ export class OpenListService {
* *
* @param filePath * @param filePath
* @param file * @param file
* @param filePathOnserver
*/ */
public async uploadFile(filePath: string, file: any): Promise<void> { public async uploadFile(
filePath: string,
file: any,
filePathOnserver: string,
): Promise<void> {
try { try {
const token = await this.fetchToken( const token = await this.fetchToken(
<string>this.configService.get('OPENLIST_API_BASE_USERNAME'), <string>this.configService.get('OPENLIST_API_BASE_USERNAME'),
<string>this.configService.get('OPENLIST_API_BASE_PASSWORD'), <string>this.configService.get('OPENLIST_API_BASE_PASSWORD'),
); );
await OpenListUtils.uploadFile(token, filePath, file); await OpenListUtils.uploadFile(token, filePath, filePathOnserver, file);
} catch (error) { } catch (error) {
this.logger.error('上传文件失败:', error); this.logger.error('上传文件失败:', error);
throw new Error('上传文件失败'); throw new Error('上传文件失败');

View File

@ -1,25 +1,63 @@
export interface UserInfo { /**
id: number; * /api/fs/list
username: string; */
email: string; export interface FsList {
role: string; code: number;
created_at: string; message: string;
updated_at: string; data: {
} content: [
name: string,
export interface DirectoryList { size: number,
path: string; is_dir: boolean,
name: string; modified: string, //修改时间
is_directory: boolean; sign: string, //签名
size: number; thumb: string, //略缩图
modified_at: string; type: number, //类型
];
total: number; //总数
readme: string; //说明?
write: boolean; //是否可写入
provider: string;
header: string;
};
} }
/**
* /api/fs/get /
*/
export interface FileInfo { export interface FileInfo {
path: string; code: number;
size: number; message: string;
mime_type: string; data: {
created_at: string; name: string;
modified_at: string; size: number;
is_directory: boolean; 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;
};
};
} }

View File

@ -1,8 +1,8 @@
import axios from 'axios'; import axios from 'axios';
import { AppConfigService } from '../../config/config.service'; import { AppConfigService } from '../../config/config.service';
import { Inject, Logger } from '@nestjs/common'; import { Inject, Logger } from '@nestjs/common';
import * as crypto from 'crypto';
import * as fs from 'fs'; import * as fs from 'fs';
import { FileInfo, FileUpload, FsList } from './openlist.types';
export class OpenListUtils { export class OpenListUtils {
private static readonly logger = new Logger(OpenListUtils.name); private static readonly logger = new Logger(OpenListUtils.name);
@ -27,10 +27,10 @@ export class OpenListUtils {
username: username, username: username,
password: password, password: password,
}); });
this.logger.debug(response); //this.logger.debug(response);
if (response.data.data.token) { if (response.data.data.token) {
const token: string = response.data.data.token; const token: string = response.data.data.token;
this.logger.log(`获取Token成功: ${token}`); this.logger.debug(`获取Token成功: ${token}`);
return token; return token;
} else { } else {
this.logger.error(`获取Token失败: ${response.data.data.message}`); 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<any> {
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 token Token
* @param path * @param path
* @returns
*/ */
static async listDirectory(token: string, path: string): Promise<any> { static async listDirectory(token: string, path: string): Promise<FsList> {
const url = `${this.apiBaseUrl}/fs/list`; const url = `${this.apiBaseUrl}/api/fs/list`;
try { try {
const response = await axios.get(url, { const response = await axios.get(url, {
params: { path }, params: { path },
headers: { Authorization: `Bearer ${token}` }, headers: { Authorization: `Bearer ${token}` },
}); });
this.logger.log('列出目录成功..'); this.logger.log(`列出目录${path}成功..`);
return response.data; return response.data;
} catch (error) { } catch (error) {
this.logger.error('列出目录失败..', error); this.logger.error(`列出目录${path}失败..`, error);
throw new Error('列出目录失败..'); throw new Error(`列出目录${path}失败..`);
} }
} }
@ -88,11 +66,9 @@ export class OpenListUtils {
* *
* @param token Token * @param token Token
* @param filePath * @param filePath
* @returns
*/ */
static async getFileInfo(token: string, filePath: string): Promise<any> { static async getFileInfo(token: string, filePath: string): Promise<FileInfo> {
const url = `${this.apiBaseUrl}/fs/info`; const url = `${this.apiBaseUrl}/fs/info`;
try { try {
const response = await axios.get(url, { const response = await axios.get(url, {
params: { path: filePath }, 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<any> {
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 * @param token Token
@ -147,24 +93,24 @@ export class OpenListUtils {
filePath: string, filePath: string,
downloadPath: string, downloadPath: string,
): Promise<void> { ): Promise<void> {
const url = `${this.apiBaseUrl}/fs/download`;
try { try {
const response = await axios.get(url, { const fileInfo = await this.getFileInfo(token, filePath);
params: { path: filePath }, const rawUrl = fileInfo.data.raw_url;
headers: { Authorization: `Bearer ${token}` }, if (!rawUrl) {
this.logger.error('文件没有找到 raw_url 地址..');
throw new Error('文件没有找到 raw_url 地址..');
}
const response = await axios.get(rawUrl, {
responseType: 'stream', responseType: 'stream',
}); });
const writer = fs.createWriteStream(downloadPath); const writer = fs.createWriteStream(downloadPath);
response.data.pipe(writer); response.data.pipe(writer);
writer.on('finish', () => { writer.on('finish', () => {
this.logger.log(`文件下载成功: ${downloadPath}`); this.logger.log(`文件下载成功: ${downloadPath}`);
}); });
writer.on('error', (error) => { writer.on('error', (error) => {
this.logger.error('下载文件失败', error); this.logger.error('下载文件失败', error);
throw new Error('下载文件失败'); throw new Error('下载文件失败..');
}); });
} catch (error) { } catch (error) {
this.logger.error('下载文件失败..', error); this.logger.error('下载文件失败..', error);
@ -173,68 +119,39 @@ export class OpenListUtils {
} }
/** /**
* *
* @param token Token * @param token Token
* @param filePath * @param filePath
* @param file * @param filePathOnServer
* @returns * @param file
*/ */
static async uploadFile( static async uploadFile(
token: string, token: string,
filePath: string, filePath: string,
file: any, filePathOnServer: string,
): Promise<any> { file: fs.ReadStream,
const url = `${this.apiBaseUrl}/fs/upload`; ): Promise<FileUpload> {
const url = `${this.apiBaseUrl}/api/fs/put`;
const formData = new FormData(); const headers = {
formData.append('file', file); Authorization: `Bearer ${token}`,
formData.append('path', filePath); 'Content-Type': 'application/octet-stream',
'Content-Length': file.bytesRead,
'File-Path': encodeURIComponent(filePathOnServer),
};
try { try {
const response = await axios.post(url, formData, { const response = await axios.put(url, file, {
headers: { headers,
Authorization: `Bearer ${token}`, params: {
'Content-Type': 'multipart/form-data', path: filePath,
'As-Task': 'true', //作为任务
}, },
}); });
this.logger.log(`文件上传成功: ${filePathOnServer}`);
this.logger.log(`文件上传成功: ${filePath}`);
return response.data; return response.data;
} catch (error) { } catch (error) {
this.logger.error('上传文件失败..', error); this.logger.error('上传文件失败..', error);
throw new Error('上传文件失败..'); throw new Error('上传文件失败..');
} }
} }
/**
*
* @param token Token
* @param directoryPath
* @returns
*/
static async listFilesInDirectory(
token: string,
directoryPath: string,
): Promise<any[]> {
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<boolean> {
const fileInfo = await this.getFileInfo(token, filePath);
return fileInfo.modified_at !== lastModified;
}
} }