| name | raw-storage |
| description | Use @dudousxd/nestjs-media's layer-1 disk-agnostic storage through MediaService.disk(name?), which returns a StorageDriver with put / get / stream / exists / delete / copy / move / size / url / temporaryUrl / list. Covers multi-disk routing (default vs named disk), PutOptions (contentType, visibility, metadata), DriverCapabilities (presign, multipart, publicUrls, list), LocalDriver vs S3Driver behaviour, and importing the framework-agnostic facade from @dudousxd/nestjs-media/storage. Explains UnknownDiskError, why temporaryUrl needs a presign-capable disk (S3, not local), and why url() on the local disk requires a baseUrl. |
| license | MIT |
| metadata | {"type":"core","library":"@dudousxd/nestjs-media","library_version":"0.5.0","framework":"nestjs"} |
Raw storage (layer 1)
When you just need a file on a disk — no entity, no media table — use the storage
layer. MediaService.disk(name?) returns a StorageDriver; with no name it
returns the configured default disk.
Setup
The storage layer is always on (it needs only default + disks, no store):
import { Injectable } from '@nestjs/common';
import { MediaService } from '@dudousxd/nestjs-media';
@Injectable()
export class ReportsService {
constructor(private readonly media: MediaService) {}
async save(id: string, csv: Buffer) {
await this.media.disk('s3').put(`reports/${id}.csv`, csv, { contentType: 'text/csv' });
return this.media.disk('s3').temporaryUrl(`reports/${id}.csv`, 300);
}
}
The full StorageDriver surface: put, get, stream, exists, delete,
copy, move, size, url, temporaryUrl, list. Source:
packages/core/src/types.ts.
Core patterns
1. Multi-disk routing
disk() with no argument is the default; pass a name to target another disk.
Stream large reads instead of buffering them:
await this.media.disk().put('tmp/import.json', buf);
const stream = await this.media.disk('local').stream('tmp/import.json');
await this.media.disk('s3').copy('a/key.bin', 'b/key.bin');
2. PutOptions and capabilities
put accepts { contentType, visibility, metadata }. Branch on the driver's
capabilities (presign, multipart, publicUrls, list) before calling
something a disk can't do:
const disk = this.media.disk('s3');
const link = disk.capabilities.presign
? await disk.temporaryUrl('reports/x.csv', 300)
: await disk.url('reports/x.csv');
3. The framework-agnostic facade — /storage
A library that needs only filesystem access (no NestJS, no media-library) imports
the storage facade directly instead of MediaService:
import { StorageManager } from '@dudousxd/nestjs-media/storage';
import { LocalDriver } from '@dudousxd/nestjs-media-disk-local';
const storage = new StorageManager({
default: 'local',
disks: { local: new LocalDriver({ root: './storage', baseUrl: 'http://localhost:3000/files' }) },
});
await storage.disk().put('a.txt', Buffer.from('hi'));
@dudousxd/nestjs-media/storage re-exports the core SPI, so there is no separate
nestjs-storage package. Source: packages/nestjs/src/storage.ts.
Common mistakes
Mistake 1 — temporaryUrl on the local disk
await this.media.disk('local').temporaryUrl('a.txt', 300);
await this.media.disk('s3').temporaryUrl('a.txt', 300);
LocalDriver.capabilities.presign is false; signed URLs require S3. Source:
packages/disk-local/src/local-driver.ts.
Mistake 2 — url() on a local disk with no baseUrl
const local = new LocalDriver({ root: './storage' });
const local = new LocalDriver({ root: './storage', baseUrl: 'http://localhost:3000/files' });
LocalDriver only sets capabilities.publicUrls (and can serve url()) when a
baseUrl is configured. Source: packages/disk-local/src/local-driver.ts.
Mistake 3 — addressing an unregistered disk name
await this.media.disk('cdn').put('a.txt', buf);
await this.media.disk('s3').put('a.txt', buf);
StorageManager.disk(name) looks the name up in the disks map and throws
UnknownDiskError when absent. Source: packages/core/src/storage-manager.ts.