Skip to content

Instantly share code, notes, and snippets.

@msukmanowsky
Last active January 10, 2023 03:50
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save msukmanowsky/c8daf3720c2839d3c535afc69234ab9e to your computer and use it in GitHub Desktop.
Save msukmanowsky/c8daf3720c2839d3c535afc69234ab9e to your computer and use it in GitHub Desktop.
// middleware.js
exports.filesUpload = function(req, res, next) {
// See https://cloud.google.com/functions/docs/writing/http#multipart_data
const busboy = new Busboy({
headers: req.headers,
limits: {
// Cloud functions impose this restriction anyway
fileSize: 10 * 1024 * 1024,
}
});
const fields = {};
const files = [];
const fileWrites = [];
// Note: os.tmpdir() points to an in-memory file system on GCF
// Thus, any files in it must fit in the instance's memory.
const tmpdir = os.tmpdir();
busboy.on('field', (key, value) => {
// You could do additional deserialization logic here, values will just be
// strings
fields[key] = value;
});
busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
const filepath = path.join(tmpdir, filename);
console.log(`Handling file upload field ${fieldname}: ${filename} (${filepath})`);
const writeStream = fs.createWriteStream(filepath);
file.pipe(writeStream);
fileWrites.push(new Promise((resolve, reject) => {
file.on('end', () => writeStream.end());
writeStream.on('finish', () => {
fs.readFile(filepath, (err, buffer) => {
const size = Buffer.byteLength(buffer);
console.log(`${filename} is ${size} bytes`);
if (err) {
return reject(err);
}
files.push({
fieldname,
originalname: filename,
encoding,
mimetype,
buffer,
size,
});
try {
fs.unlinkSync(filepath);
} catch (error) {
return reject(error);
}
resolve();
});
});
writeStream.on('error', reject);
}));
});
busboy.on('finish', () => {
Promise.all(fileWrites)
.then(() => {
req.body = fields;
req.files = files;
next();
})
.catch(next);
});
busboy.end(req.rawBody);
}
@Dastagiraiah
Copy link

I used this to upload image into firebase but it didn't work

@msukmanowsky
Copy link
Author

@191611007 sorry to hear that, what was the error you got?

@Dastagiraiah
Copy link

I tried to upload an image. I selected a file in postman, it's just got executed but there is no error and no image in firbase storage

@msukmanowsky
Copy link
Author

Hmm it's tough to debug that on my end without some more details. Want to provide some sample code?

@Dastagiraiah
Copy link

Error: Bucket name not specified or invalid. Specify a valid bucket name via the storageBucket option when initializing the app, or specify the bucket name explicitly when calling the getBucket() method.
at new FirebaseError (/srv/node_modules/firebase-admin/lib/utils/error.js:42:28)
at Storage.bucket (/srv/node_modules/firebase-admin/lib/storage/storage.js:107:15)
at Busboy.busboy.on (/srv/handlers.js/users.js:108:25)
at emitNone (events.js:106:13)
at Busboy.emit (events.js:208:7)
at Busboy.emit (/srv/node_modules/busboy/lib/main.js:37:33)
at UrlEncoded.end (/srv/node_modules/busboy/lib/types/urlencoded.js:211:12)
at Busboy.emit (/srv/node_modules/busboy/lib/main.js:30:36)
at finishMaybe (_stream_writable.js:613:14)
at afterWrite (_stream_writable.js:464:3)

@Dastagiraiah
Copy link

exports.uploadImage = (req, res) => {

const BusBoy = require('busboy');
const path = require('path');
const os = require('os');
const fs = require('fs');

const busboy = new BusBoy({headers: req.headers});
let imageFileName;
let imageTobeUploaded = {};
busboy.on('file',(fieldname, file, filename, encoding, mimeType) => {
    //my.image.png
    const imageExtension = filename.split('.')[filename.split('.').length - 1];
    //12345678900.png
    imageFileName = `${Math.round(Math.random()*100000000000)}.${imageExtension}`;
    const filepath = path.join(os.tmpdir(), imageFileName);
    imageTobeUploaded = {filepath, mimeType};
    file.pipe(fs.createWriteStream(filepath)); 
})
busboy.on('finish', () => {
    admin.storage().bucket().upload(imageTobeUploaded.filepath, {
        resumable: false,
        metadata:{
            metadata:{
                contentType:imageTobeUploaded.mimeType
            }
        }
    })
    .then( () => {
        const imageUrl = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media`
       // return db.doc(`/users/${req.user.handle}`).update({imageUrl});
    })
    .then( () => {
        return res.json({message: "Image Uploaded Successfully"});
    })
    .catch(err => {
        console.error(err);
        return res.status(400).json({ error : err.code});
    })
});
busboy.end(req.rawBody);

};

@Dastagiraiah
Copy link

Dastagiraiah commented Jan 19, 2020

I tried with different code
I got different error previously like below
SyntaxError: Unexpected token o in JSON at position 1

now I got that bucket invalid error

@Dastagiraiah
Copy link

TypeError: Path must be a string. Received undefined
at assertPath (path.js:28:11)
at Object.basename (path.js:1377:5)
at Bucket.upload (/srv/node_modules/@google-cloud/storage/build/src/bucket.js:2345:38)
at PromiseCtor (/srv/node_modules/@google-cloud/promisify/build/src/index.js:71:28)
at new Promise ()
at Bucket.wrapper (/srv/node_modules/@google-cloud/promisify/build/src/index.js:56:16)
at Busboy.busboy.on (/srv/handlers.js/users.js:108:34)
at emitNone (events.js:106:13)
at Busboy.emit (events.js:208:7)
at Busboy.emit (/srv/node_modules/busboy/lib/main.js:37:33)

if I do firebase deploye then I am getting above path error
if I do firebase serve then I am getting bucket error

@Dastagiraiah
Copy link

TypeError: Path must be a string. Received undefined
at assertPath (path.js:28:11)
at Object.basename (path.js:1377:5)
at Bucket.upload (/srv/node_modules/@google-cloud/storage/build/src/bucket.js:2345:38)
at PromiseCtor (/srv/node_modules/@google-cloud/promisify/build/src/index.js:71:28)
at new Promise ()
at Bucket.wrapper (/srv/node_modules/@google-cloud/promisify/build/src/index.js:56:16)
at Busboy.busboy.on (/srv/handlers.js/users.js:108:34)
at emitNone (events.js:106:13)
at Busboy.emit (events.js:208:7)
at Busboy.emit (/srv/node_modules/busboy/lib/main.js:37:33)
If I do firebase deploy I am getting above path error
if I do firebase serve then It will be bucket error

help me out this bro

@Dastagiraiah
Copy link

I found the error

in admin.storage().bucket() there should give storage bucket as bucket(config.storageBucket)

@msukmanowsky
Copy link
Author

🎉 🎆 👍

@abhayverma47
Copy link

thanks

@VanSon999
Copy link

I have set 'fileSize: 500 * 1024' (500KB). But when I upload a file larger than 1MB in size it still happens normally! No error occurred! Please help!

@jayjaydluffy
Copy link

@msukmanowsky the next step (in your usage.js) to upload it to Cloud Storage will be via admin.storage() or firebase.storage()? Is the files in req.files of type File? i don't seem to find a way to upload File types via admin.storage() whereas I can do it with firebase.storage(), can't I? Please help. If you have gists on how you upload it after the middleware then pls share also. thanks

@jeanpierregomez
Copy link

@jayjaydluffy do you can solve this?

@AliKORKMAZ53
Copy link

i modified the code and here is working version for me:

`var busboy = new Busboy({ headers: req.headers });
const bucket = storage.bucket('buketdeneme');
let mimtype;
var saveTo;

busboy.on('file', function(name, file, filename, encoding, mimetype) {
  console.log('File [' + name + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
  const imageExtension = filename.split('.')[filename.split('.').length - 1];
  var fname=filename+'.'+imageExtension;
  saveTo = path.join(os.tmpdir(), filename);
  file.pipe(fs.createWriteStream(saveTo));
  mimtype=mimetype;
  
});

busboy.on('finish', async function() {
	await bucket.upload(saveTo, {
    resumable: false,
	gzip: true,
    metadata:{
		metadata:{
            contentType:mimtype
		}
		}
})
.then( () => {
    return res.json({message: "Image Uploaded Successfully"});
})
.catch(err => {
    console.error(err);
    return res.status(400).send(JSON.stringify(err, ["message", "arguments", "type", "name"]));
});
  
  res.end();
});
req.pipe(busboy);`

@babacarMbengue12
Copy link

thanks !!

@dungphanxuan
Copy link

Hi, can you show me solution for embed in code,
https://github.com/ThalKod/DropIt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment