Files
paperlessmanager/paperless-backend/src/postprocessing/export.service.ts
T

115 lines
3.7 KiB
TypeScript

import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { ExportTarget } from '../database/entities/export-target.entity';
import * as ftp from 'basic-ftp';
import { createClient, type WebDAVClient } from 'webdav';
@Injectable()
export class ExportService {
private readonly logger = new Logger(ExportService.name);
constructor(
@InjectRepository(ExportTarget) private readonly targetRepo: Repository<ExportTarget>,
) {}
async exportFile(targetId: number, filename: string, content: Buffer): Promise<void> {
const target = await this.targetRepo.findOneByOrFail({ Id: targetId });
if (!target.IsActive) {
throw new Error(`Export-Ziel "${target.Name}" ist deaktiviert.`);
}
switch (target.Protocol) {
case 'ftp':
await this.uploadFtp(target, filename, content);
break;
case 'webdav':
await this.uploadWebDav(target, filename, content);
break;
default:
throw new Error(`Unbekanntes Protokoll: ${target.Protocol}`);
}
}
async testConnection(targetId: number): Promise<{ success: boolean; message: string }> {
const target = await this.targetRepo.findOneByOrFail({ Id: targetId });
try {
switch (target.Protocol) {
case 'ftp':
await this.testFtp(target);
break;
case 'webdav':
await this.testWebDav(target);
break;
default:
return { success: false, message: `Unbekanntes Protokoll: ${target.Protocol}` };
}
return { success: true, message: 'Verbindung erfolgreich.' };
} catch (err: any) {
return { success: false, message: err.message };
}
}
private async uploadFtp(target: ExportTarget, filename: string, content: Buffer): Promise<void> {
const client = new ftp.Client();
try {
await client.access({
host: target.Host,
port: target.Port || 21,
user: target.Username || 'anonymous',
password: target.Password || '',
secure: false,
});
const remotePath = `${target.RemotePath || '/'}/${filename}`;
const { Readable } = await import('stream');
const stream = Readable.from(content);
await client.uploadFrom(stream, remotePath);
this.logger.log(`FTP Upload: ${remotePath}${target.Name}`);
} finally {
client.close();
}
}
private async testFtp(target: ExportTarget): Promise<void> {
const client = new ftp.Client();
try {
await client.access({
host: target.Host,
port: target.Port || 21,
user: target.Username || 'anonymous',
password: target.Password || '',
secure: false,
});
await client.list(target.RemotePath || '/');
} finally {
client.close();
}
}
private async uploadWebDav(target: ExportTarget, filename: string, content: Buffer): Promise<void> {
const client = this.createWebDavClient(target);
const remotePath = `${target.RemotePath || '/'}/${filename}`;
await client.putFileContents(remotePath, content);
this.logger.log(`WebDAV Upload: ${remotePath}${target.Name}`);
}
private async testWebDav(target: ExportTarget): Promise<void> {
const client = this.createWebDavClient(target);
await client.getDirectoryContents(target.RemotePath || '/');
}
private createWebDavClient(target: ExportTarget): WebDAVClient {
const protocol = target.Port === 443 ? 'https' : 'http';
const port = target.Port ? `:${target.Port}` : '';
const url = `${protocol}://${target.Host}${port}`;
return createClient(url, {
username: target.Username || undefined,
password: target.Password || undefined,
});
}
}