Merge branch 'local-uploader' into 'main'

Add localUploader

See merge request soapbox-pub/ditto!194
This commit is contained in:
Alex Gleason 2024-04-29 21:31:38 +00:00
commit 36aaf79a74
3 changed files with 48 additions and 5 deletions

View File

@ -139,6 +139,10 @@ class Conf {
static get uploader() { static get uploader() {
return Deno.env.get('DITTO_UPLOADER'); return Deno.env.get('DITTO_UPLOADER');
} }
/** Location to use for local uploads. */
static get uploadsDir() {
return Deno.env.get('UPLOADS_DIR') || 'data/uploads';
}
/** Media base URL for uploads. */ /** Media base URL for uploads. */
static get mediaDomain() { static get mediaDomain() {
const value = Deno.env.get('MEDIA_DOMAIN'); const value = Deno.env.get('MEDIA_DOMAIN');

View File

@ -1,7 +1,8 @@
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { ipfsUploader } from './ipfs.ts'; import { ipfsUploader } from '@/uploaders/ipfs.ts';
import { s3Uploader } from './s3.ts'; import { localUploader } from '@/uploaders/local.ts';
import { s3Uploader } from '@/uploaders/s3.ts';
import type { Uploader } from './types.ts'; import type { Uploader } from './types.ts';
@ -10,8 +11,8 @@ const configUploader: Uploader = {
upload(file, opts) { upload(file, opts) {
return uploader().upload(file, opts); return uploader().upload(file, opts);
}, },
delete(cid, opts) { delete(id, opts) {
return uploader().delete(cid, opts); return uploader().delete(id, opts);
}, },
}; };
@ -22,8 +23,10 @@ function uploader() {
return s3Uploader; return s3Uploader;
case 'ipfs': case 'ipfs':
return ipfsUploader; return ipfsUploader;
case 'local':
return localUploader;
default: default:
return ipfsUploader; throw new Error('No `DITTO_UPLOADER` configured. Uploads are disabled.');
} }
} }

36
src/uploaders/local.ts Normal file
View File

@ -0,0 +1,36 @@
import { join } from 'node:path';
import { crypto } from '@std/crypto';
import { encodeHex } from '@std/encoding/hex';
import { extensionsByType } from '@std/media-types';
import { Conf } from '@/config.ts';
import type { Uploader } from './types.ts';
/** Local filesystem uploader. */
const localUploader: Uploader = {
async upload(file) {
const sha256 = encodeHex(await crypto.subtle.digest('SHA-256', file.stream()));
const ext = extensionsByType(file.type)?.[0] ?? 'bin';
const filename = `${sha256}.${ext}`;
await Deno.mkdir(Conf.uploadsDir, { recursive: true });
await Deno.writeFile(join(Conf.uploadsDir, filename), file.stream());
const { mediaDomain } = Conf;
const url = new URL(mediaDomain);
const path = url.pathname === '/' ? filename : join(url.pathname, filename);
return {
id: filename,
sha256,
url: new URL(path, url).toString(),
};
},
async delete(id) {
await Deno.remove(join(Conf.uploadsDir, id));
},
};
export { localUploader };