1

Having a problem when uploading to firebase cloud functions.. I'm using busboy and sharp to achieve this but every time I run my code it only return "finished with status: 'timeout'" with no error...

this code will work without the sharp resize function please see below code for reference.

const fs = require("fs");
const os = require("os");
const path = require("path");
const Busboy = require("busboy");
const config = require('../config');
const gcs = config.get('gcs');
const UUID = require('uuidv4')
const sharp = require('sharp');


 let insertStorageMaterials = (req,callback) =>{
  const busboy = new Busboy({ headers: req.headers });
  let uploadData = null;
  let origFileName;

  busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
    origFileName = filename
    const filepath = path.join(os.tmpdir(), filename);
    uploadData = { file: filepath, type: mimetype };
    file.pipe(fs.createWriteStream(filepath));

  });

  busboy.on("finish", () => {
    const bucket = gcs.bucket(bucketName);
    let uuid = UUID();

    sharp(uploadData.file)
    .resize(500, 500)
    .toFile(uploadData.file)
    .then(data => {
      console.log("data",data)
      bucket
      .upload(uploadData.file, {
        uploadType: "media",
        metadata: {
          metadata: {
            contentType: uploadData.type,
            firebaseStorageDownloadTokens: uuid
          }
        },
        destination:"Materials/test/"+origFileName  
    })
    return data
  }).then(data=>{
      let file = data[0];
      let dataURL = "https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent(file.name) + "?alt=media&token=" + uuid;
      console.log("url",dataURL)
      return callback(false,{dataURL:dataURL,name:origFileName,message:"Success!"});
    .catch(error =>{
      return error;
    })
  })

  busboy.end(req.rawBody);

  }

module.exports = {
  insertStorageMaterials:insertStorageMaterials
}

express call

//index.js
const app = express();
const appUsers = require('./Routes/userRoute')

const api = fbFunc.https.onRequest(app);

app.post(['/uploadMaterials'],appUsers);


module.exports = {api}

//Routes
const userFunc = require('../Functions/userFunc')

apiCalls.post('/uploadMaterials',(req,res)=>{
    userFunc.uploadMaterials(req,(err,result)=>{
      if (err) return res.status(500).send('Internal Server Error')
      return res.status(200).send(result);
  })
})

EDIT:

  sharp(uploadData.file)
    .resize(500, 500)
    .toFile(uploadData.file)
    .then(data => {
      console.log("datadddd",data)
      return bucket
      .upload(uploadData.file, {
        uploadType: "media",
        metadata: {
          metadata: {
            contentType: uploadData.type,
            firebaseStorageDownloadTokens: uuid
          }
        },
        destination:"Materials/test/"+origFileName  
    })

  .then(data=>{
      let file = data[0];
      let dataURL = "https://firebasestorage.googleapis.com/v0/b/" + bucket.name + "/o/" + encodeURIComponent(file.name) + "?alt=media&token=" + uuid;
      console.log("url",dataURL)
      return callback(false,{dataURL:dataURL,name:origFileName,message:"Success!"});
    })
    .catch(error =>{
      return error;
    })

}).catch(error =>{
  return error;
})
  })
Renz M
  • 87
  • 10

2 Answers2

0

Not sure if the issue is for the resize API, but did you try using toBuffer method instead of toFile?

sharp(input)
    .resize(500, 500)
    .toBuffer()
    .then(data => {
    // Convert data to image file
    });

You can convert the image buffer to file using the accepted answer here - NodeJS write base64 image-file

0

HTTP functions terminate when you send a response back to the client. Since you're never sending a response, the function will just time out waiting for that response. Use that res object that Express is passing to your code.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • I do send something back to the client, just didn't include it earlier, like i said it does work without the sharp library. – Renz M Dec 17 '18 at 09:48
  • It's impossible to tell because you're still not showing the entire code. You're omitted parts of it, and I can't see how it all fits together. – Doug Stevenson Dec 17 '18 at 17:00
  • I've added everything now. – Renz M Dec 18 '18 at 00:24
  • I'd guess you're still not returning a result because you're not dealing with promises correctly. I don't think your `return data` line is doing what you expect. Think carefully about how data flows through your function, and add debug logs everywhere to see what's not being invoked. – Doug Stevenson Dec 18 '18 at 00:48
  • Each then() should return a value or throw this shows if i remove the return data; but I don't want to return anything until the upload is finish. any suggestion how should i do that? – Renz M Dec 18 '18 at 01:25
  • upload() returns another promise, doesn't it? – Doug Stevenson Dec 18 '18 at 01:31
  • you mean I should return the bucket.upload? please see the edit part if I'm doing it correctly.. tried that and it does not work.. :( – Renz M Dec 18 '18 at 01:58
  • Have you tried adding debug logging to make sure all the values are what you expect at every step? – Doug Stevenson Dec 18 '18 at 02:09
  • When I say "at every step", I mean throughout your code to make sure all values are what you expect. I can't really go back and forth debugging your code with you - you'll need to identify a specific issue that you don't understand or are unable to debug further. – Doug Stevenson Dec 18 '18 at 02:25