0

What Changes do I need to make in order to proceed with this task. There isn't much documentation on how to upload multiple files to google cloud. I have some experience with nodejs please contribute. I'm able to do it for single upload but not for multiple upload. This code basically should do what says in the question

Here's my route

router.post('/:pid/images',
fileUpload.multer.array('images', 6),
fileUpload.sendUploadToGCS,
postsControllers.addImagestoPost);

Here's my fileUpload.js

const Multer = require('multer');
const { uuid } = require('uuidv4');
const {Storage} = require('@google-cloud/storage');
const path = require('path');

const MIME_TYPE_MAP = {
  'image/png': 'png',
  'image/jpeg': 'jpeg',
  'image/jpg': 'jpg',
};

const gc = new Storage({
  keyFilename: path.join(__dirname,'../########.json'),
  projectId: '#####'
});

const craigFilesBucket = gc.bucket('craig-files');

function getPublicUrl(filename) {
  return `https://storage.googleapis.com/craig-files/${filename}`;
}

function sendUploadToGCS(req, res, next){
  if(!req.file){
    return next();
  }

  const gcsname = uuid() + req.file.originalname;
  const file = craigFilesBucket.file(gcsname);

  const stream = file.createWriteStream({
    metadata: {
      contentType: req.file.mimetype,
    },
    resumable: false
  });

  stream.on('error', err =>{
    req.file.cloudStorageError = err;
    next(err);
  });

  stream.on('finish', async () => {
    req.file.cloudStorageObject = gcsname;
    await file.makePublic();
    req.file.cloudStoragePublicUrl = getPublicUrl(gcsname);
    next();
  });

  stream.end(req.file.buffer);
}

const multer = Multer({
  storage: Multer.MemoryStorage,
  limits: {
    fileSize: 10 * 1024 * 1024,   // no longer than 10mb
  }
});

module.exports = {
  getPublicUrl,
  sendUploadToGCS,
  multer
};

Here is my controller

const addImagestoPost = async (req, res, next) =>{
  const errors = validationResult(req);
  if(!errors.isEmpty()){
    return next(new HttpError('Invalid inputs passed, please check your data.', 422))
  }

  const postId = req.params.pid;

  let post;
  try{
    post = await Post.findById(postId);
  }catch(err){
    const error = new HttpError(
      'Something went wrong could not update post',
      500
    );
    return next(error);
  }

  if(!req.file || !req.file.cloudStoragePublicUrl){
    return next(new HttpError('cloudStoragePublicUrl err.', 422))
  }

  post.images.push(req.file.cloudStoragePublicUrl);

  try{
    await post.save();
  }catch(err){
    const error = new HttpError(
      'Something went wrong, could not update post', 500
    )
  }

  res.status(200).json({post: post.toObject({getters: true})})
}

1 Answers1

0

The API itself does not contain multiply upload of the files. So if you are able to upload one file I suggest to implement some method that will loop over your files.

You may take a look as well on "convenience method" Bucket.upload which I think is very nice equivalent of File.createWriteStream.

Dharman
  • 30,962
  • 25
  • 85
  • 135
vitooh
  • 4,132
  • 1
  • 5
  • 16
  • So it's almost working but now I have two asynchronous code in two different files which depends on the first one. But they are executing at the same time which is a problem. I want the first code in first file to run first and then the second one in second file. Please let me know how can I achieve that – Rajan Baliwal Aug 07 '20 at 08:42
  • Seems that you need to run "asynchronous code synchronously" this is known problem. Try to search for this. example You can check this https://stackoverflow.com/questions/9121902/call-an-asynchronous-javascript-function-synchronously, or https://medium.com/@patarkf/synchronize-your-asynchronous-code-using-javascripts-async-await-5f3fa5b1366d – vitooh Aug 07 '20 at 09:27