123 lines
3.3 KiB
TypeScript
Raw Normal View History

2023-04-13 08:45:44 +02:00
import type { ReadStream } from 'node:fs';
import { v2 as cloudinary, ConfigOptions, UploadApiOptions } from 'cloudinary';
import intoStream from 'into-stream';
2023-06-26 17:24:32 +02:00
import * as utils from '@strapi/utils';
2018-03-24 12:08:07 +01:00
2023-04-13 08:45:44 +02:00
interface File {
name: string;
alternativeText?: string;
caption?: string;
width?: number;
height?: number;
formats?: Record<string, unknown>;
hash: string;
ext?: string;
mime: string;
size: number;
url: string;
previewUrl?: string;
path?: string;
provider?: string;
provider_metadata?: Record<string, unknown>;
stream?: ReadStream;
buffer?: Buffer;
}
2018-03-24 12:08:07 +01:00
2023-04-13 08:45:44 +02:00
export = {
init(options: ConfigOptions) {
cloudinary.config(options);
2018-03-24 12:08:07 +01:00
2023-04-13 08:45:44 +02:00
const upload = (file: File, customConfig = {}): Promise<void> => {
return new Promise((resolve, reject) => {
const config: Partial<UploadApiOptions> = {
2022-01-05 19:02:04 +01:00
resource_type: 'auto',
public_id: file.hash,
};
2022-01-05 19:02:04 +01:00
if (file.ext) {
config.filename = `${file.hash}${file.ext}`;
}
2023-02-02 15:48:27 +01:00
if (file.path) {
config.folder = file.path;
}
2023-02-02 15:48:27 +01:00
const uploadStream = cloudinary.uploader.upload_chunked_stream(
2022-01-05 19:02:04 +01:00
{ ...config, ...customConfig },
(err, image) => {
if (err) {
if (err.message.includes('File size too large')) {
2023-04-13 08:45:44 +02:00
reject(new utils.errors.PayloadTooLargeError());
2022-08-05 11:51:47 +02:00
} else {
reject(new Error(`Error uploading to cloudinary: ${err.message}`));
}
2022-08-05 11:51:47 +02:00
return;
2022-01-05 19:02:04 +01:00
}
2023-04-13 08:45:44 +02:00
if (!image) {
return;
}
2022-01-05 19:02:04 +01:00
if (image.resource_type === 'video') {
file.previewUrl = cloudinary.url(`${image.public_id}.gif`, {
video_sampling: 6,
delay: 200,
width: 250,
crop: 'scale',
resource_type: 'video',
});
}
2022-01-05 19:02:04 +01:00
file.url = image.secure_url;
file.provider_metadata = {
public_id: image.public_id,
resource_type: image.resource_type,
};
2022-08-08 23:33:39 +02:00
2022-01-05 19:02:04 +01:00
resolve();
}
);
2022-08-08 23:33:39 +02:00
if (file.stream) {
2023-02-02 15:45:04 +01:00
file.stream.pipe(uploadStream);
2023-04-13 08:45:44 +02:00
} else if (file.buffer) {
2022-08-08 23:33:39 +02:00
intoStream(file.buffer).pipe(uploadStream);
2023-04-13 08:45:44 +02:00
} else {
throw new Error('Missing file stream or buffer');
2022-08-08 23:33:39 +02:00
}
2022-01-05 19:02:04 +01:00
});
2023-04-13 08:45:44 +02:00
};
2022-01-05 19:02:04 +01:00
return {
2023-04-13 08:45:44 +02:00
uploadStream(file: File, customConfig = {}) {
2022-01-05 19:02:04 +01:00
return upload(file, customConfig);
},
2023-04-13 08:45:44 +02:00
upload(file: File, customConfig = {}) {
2022-01-05 19:02:04 +01:00
return upload(file, customConfig);
2018-03-24 12:08:07 +01:00
},
2023-04-13 08:45:44 +02:00
async delete(file: File, customConfig = {}) {
2018-03-24 12:08:07 +01:00
try {
2023-04-13 08:45:44 +02:00
const { resource_type: resourceType, public_id: publicId } = file.provider_metadata ?? {};
const deleteConfig = {
resource_type: (resourceType || 'image') as string,
2019-04-27 12:09:07 +02:00
invalidate: true,
...customConfig,
2023-04-13 08:45:44 +02:00
};
const response = await cloudinary.uploader.destroy(`${publicId}`, deleteConfig);
if (response.result !== 'ok' && response.result !== 'not found') {
2023-04-13 08:45:44 +02:00
throw new Error(response.result);
2018-03-24 12:08:07 +01:00
}
} catch (error) {
2023-04-13 08:45:44 +02:00
if (error instanceof Error) {
throw new Error(`Error deleting on cloudinary: ${error.message}`);
}
throw error;
2018-03-24 12:08:07 +01:00
}
2019-04-27 12:09:07 +02:00
},
2018-03-24 12:08:07 +01:00
};
2019-04-27 12:09:07 +02:00
},
2018-03-24 12:08:07 +01:00
};