What's the difference between the 'field' and the 'file' events in busboy?
Asked Answered
C

2

2

Busboy is the middleware I'm using to upload a file. Using an html form inside Chrome, I can upload files (using the 'file' event) but when an android client tries to upload a file, it doesn't trigger the 'file' event, it triggers the 'field' event instead.

Here the code snippet I am using on the server side:

import express from 'express';
import busboy from 'connect-busboy';

const app = express();

const busUpload = (req, res)=> {
    req.busboy.on('file', function(fieldname, file, filename, encoding, mimetype) {
        saveTo = `${destination}/${filename}`;

        Log('uploading to', saveTo);
        file.pipe(fs.createWriteStream(saveTo));
        // file is saved successfully.
    });

    req.busboy.on('field', function(key, value, keyTruncated, valueTruncated) {
    //  I guess 'value' contains the file, but how do I save it? what is the name of file?
    });

    req.busboy.on('finish', function() {
        Log('upload completed');
        // res.writeHead(200, {'Connection': 'close'});
        res.json({sucess: true});
    });

    // req.pipe(req.busboy);

};

‍‍app.use('/uploads', busboy({immediate: true}), busUpload)

‍‍‍What's the difference? What should I tell the android developer to change in his request? Or how can I save the file inside the handler of the 'field' event?

Clorindaclorinde answered 26/8, 2018 at 9:57 Comment(0)
S
1

According to the busboy documentation the file event is triggered for file uploads:

  • Emitted for each new file form field found. transferEncoding contains the 'Content-Transfer-Encoding' value for the file stream. mimeType contains the 'Content-Type' value for the file stream.

Since you get a field event my guess would be that the input is not sent similarly as in an html file input element:

<input type="file" name="filename" accept="media/type">

I am not familiar with android API so not sure how files are sent, but since your field event is triggered it seems you should dive into the client side (Android) of the code and see what possibilities you have.

Alternatively you can validate whether your field input contains a file like you already suggested in the code snippet in your question above:

//  I guess 'value' contains the file, but how do I save it? what is the name of file?

You can simply check what you get from your client by debugging/analyzing/logging your request object.


If you don't have the possibility to work on the client side code yourself, you could also try building a small html upload page where you upload files to your server and see what behavior you get. Like that you will be able to check easily if your server is working as expected. In this small application could upload files in different ways:

  1. through a form as in the example here
  2. as binary content as in the example here

And test whether your server is able to handle the file correctly in both cases.

Symbolic answered 27/8, 2018 at 7:6 Comment(3)
Thanks. I did log the value and it seems to be the buffer of the file which I don't think I can get the filename out of it. using formidable instead of busboy, and doing console.log({fields, files}) I could understand that when I upload from browser, there is a key filename(as in <input name="filename") inside files but when I upload from android, the key is not in files but is in fields so I guess android is sending the file without type="file" in the input field. it's like it's a binary which comes in a text field. and it seems that's why busboy doesn't find the file.Clorindaclorinde
You probably can get the file name from one of the request headers. Log your req.headers object and check what you get. Probably you will have a content-disposition header in there from which you can read the file name.Symbolic
Also check with your android developer whether he/she follows best practices for file uploading. It might be you get this unexpected behavior on your server because the code on the Android client is not following protocol.Symbolic
C
0

Simply put, a field event happens for any text field etc. Any data in form being passed in text field can be accessed via field event.

The file event occurs, if user uploads any file. The file can be accessed via registering event handler for file events and the file data can be read via data event in that.

so the code for file upload goes something like,

const bb = Busboy({ headers: req.headers });
bb.on('file', (name, file, info) => {
  let saveLocation = path.join(__dirname, '/');
  file.on('data', (data) => {
    console.log('some chunk received: ', data.length);
  })
  file.on('close',()=>{
    console.log('file reading done.')
  })
  file.pipe(fs.createWriteStream(saveLocation));
});
Cannot answered 6/5, 2023 at 17:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.