2

I want to upload a file using cloudinary but it's not working. What it the file string parameter should be?

@Injectable()
export class CloudinaryService {
  async uploadImage(
    file: Express.Multer.File,
    id: string,
  ): Promise<UploadApiResponse | UploadApiErrorResponse> {
    return new Promise((resolve, reject) => {
      v2.uploader.upload(
        file.filename,
        { public_id: id, folder: 'business', resource_type: 'auto' },
        (error, result) => {
          if (error) return reject(error);
          resolve(result);
        },
      );
    });
  }
}

Here's the file object

{
  fieldname: 'DirectorsDetails',
  originalname: 'Eddy - Information about directors.xlsx',
  encoding: '7bit',
  mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  buffer: <Buffer 50 4b 03 04 14 00 08 08 08 00 14 2a be 52 00 00 00 00 00 00 00 00 00 00 00 00 18 00 00 00 78 6c 2f 64 72 61 77 69 6e 67 73 2f 64 72 61 77 69 6e 67 31 ... 5072 more bytes>,
  size: 5122
}
0

3 Answers 3

1

Try this see if it helps:

Tune the multer to use memory storage for getting buffer in later stage

// app.module.ts
import { MulterModule } from '@nestjs/platform-express';
import { memoryStorage } from 'multer';

@Module({
  imports: [
    ...
    MulterModule.register({
      storage: memoryStorage(), // use memory storage for having the buffer
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

Turning buffer to stream and bootstrap it to upload

import { Injectable } from '@nestjs/common';
import { UploadApiErrorResponse, UploadApiResponse, v2 } from 'cloudinary';
import { Readable } from 'stream';

@Injectable()
export class CloudinaryService {
  async uploadImage(
    file: Express.Multer.File,
  ): Promise<UploadApiResponse | UploadApiErrorResponse> {
    return new Promise((resolve, reject) => {
      const upload = v2.uploader.upload_stream((error, result) => {
        if (error) return reject(error);
        resolve(result);
      });
      Readable.from(file.buffer).pipe(upload); // covert buffer to readable stream and pass to upload
    });
  }
}

If you want to save it to local directory first, you can do it but you will need to read the file from path via fs.createReadStream to make a stream of it and upload it to cloudinary.


If you cannot make it works, I can upload a example to github for you to cross-check.

Sign up to request clarification or add additional context in comments.

Comments

0

file.filename is only populated if you store multer files on disk. Perhaps file.originalname is the property you're looking for.

1 Comment

even with that it says ENOENT: no such file or directory, open filename
0

Try using upload_stream function.

import { FileUpload } from 'graphql-upload';

export class CloudinaryService {
  async uploadImage(
    file: FileUpload,
  ): Promise<UploadApiResponse | UploadApiErrorResponse> {
    return new Promise((resolve, reject) => {
      const upload = v2.uploader.upload_stream((error, result) => {
        if (error) return reject(error);
        resolve(result);
      });

      file.createReadStream().pipe(upload);
    });
  }
}

4 Comments

It says Property 'createReadStream' does not exist on type 'File'
I've updated the answer with the type I use.
Still same file.createReadStream is not a function
I added the file object to the question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.