Машинопись: Sharp. js преобразовать поток в несколько размеров и загрузить его на S3 - PullRequest
0 голосов
/ 04 февраля 2020

Сценарий здесь:
Шаг 1: Получить загруженное изображение из GraphQL (Итак, это ReadableStream)
Шаг 2: Использовать Sharp для генерации размеров изображения
Шаг 3: Загрузить все размеры изображения на S3

Вот мой код

UploadRepository.ts

import {FileUpload} from "graphql-upload";
import {S3Client} from "../../services/aws-s3-client";
import uuid from "uuid/v4";
import {MediaUpload} from "../../entity/MediaUpload";
import sharp from "sharp";

const resizeImageWidth = [200, 408, 560, 692, 800];

export class UploadRepository {

    protected s3client: S3Client;

    constructor() {
        this.s3client = new S3Client()
    }

    async uploadImage(fileUpload: FileUpload): Promise<MediaUpload> {
        try {
            const extension = fileUpload.filename.split('.').slice(-1)[0];
            const fileNamePrefix = uuid();
            const transform  = sharp();

            for (const imageSize of resizeImageWidth) {
                const fileNameWithSizeAndExtenstion = `${fileNamePrefix}_${imageSize}.${extension}`;
                transform
                    .clone()
                    .resize(imageSize)
                    .webp()
                    .pipe(this.s3client)
                    .put(fileNameWithSizeAndExtenstion, fileUpload.mimetype, fileUpload.encoding);
            }

            fileUpload.createReadStream().pipe(transform);

            // Trying the get the response from the S3 Promises provided to the transform

            return {
                fileName: fileUpload.filename,
                mimeType: fileUpload.mimetype,
                urls: ['', '']
            };
        } catch (e) {
            console.log(e);
            throw new Error(e)
        }
    }

}

s3Client.ts

import {default as S3} from "aws-sdk/clients/s3";
import {ManagedUpload} from "aws-sdk/lib/s3/managed_upload";
import moment from "moment";
import {Writable, WritableOptions} from "stream";

export class S3Client extends Writable{

    protected client: S3;

    protected data: any;

    constructor(opts?: WritableOptions) {
        super(opts);
        this.client = new S3({
            accessKeyId: process.env.AWS_ACCESS_KEY,
            secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
            region: process.env.S3_REGION
        })
    }

    _write(chunk: any) {
        this.data += chunk;
    }

    public put(fileName: string, mimeType: string, encoding: string): Promise<ManagedUpload.SendData> {
        return this.client.upload({
            Bucket: `${process.env.S3_BUCKET}/${this.getLocaiton()}`,
            Key: fileName,
            Body: this.data,
            ContentType: `${mimeType}; charset=utf-8`,
            ACL: 'public-read',
            CacheControl: 'max-age=60',
            ContentEncoding: encoding
        }).promise();
    }

    getLocaiton(): string {
        const yearMonthFolder = moment().format('YYYY/MM');
        return `uploads/${yearMonthFolder}`;
    }
}

Я застрял здесь в том, как собрать ответ на все обещания и вернуть Местоположение S3.

Заранее спасибо.

...