0

I'm trying to pass a blob of audio file from my react application to Express backend using formData, but I kept on getting undefined when I try to retrieve the data on the backend.

Frontend code:

var fd = new FormData();
fd.append('fname', 'test.webm');
fd.append('data', blob);

payload = {audioFile: fd};

axios.post('/translate-audio', payload, {headers: {'content-type': 'multipart/form-data'}})

backend code:

app.use(cors());
app.use(express.json());

app.post('/translate-audio', async (req, res) => {
    console.log(req.body.audioFile);
});

Side note:

I was able to see the file when I ran console.log(payload.audioFile.get('data')); on the frontend:

File {name: 'blob', lastModified: 1636600689885, lastModifiedDate: Wed Nov 10 2021 19:18:09 GMT-0800 (Pacific Standard Time), webkitRelativePath: '', size: 10828, …}
    lastModified: 1636600689885
    lastModifiedDate: Wed Nov 10 2021 19:18:09 GMT-0800 (Pacific Standard Time) {}
    name: "blob"
    size: 10828
    type: "audio/webm;codecs=opus"
    webkitRelativePath: ""

Any help is greatly appreciated. I just need to pass the blob correctly to the backend, so other alternative without using formData will be helpful as well. Also, what is a good way to do this the other way around (sending audio blob from server to frontend)?

  • You might also want to look at using buffers: `blob`[`.arrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer)/[`.stream`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/stream), [`express.raw`](https://expressjs.com/en/4x/api.html#express.raw) – jsejcksn Nov 11 '21 at 04:08

1 Answers1

0

You can't serialise FormData into JSON. Send the FormData as your request data directly and use middleware like Multer to handle it server-side

Frontend

const fd = new FormData()
fd.append("audioFile", blob, "test.webm")

// Do not customise the content-type header.
// See https://stackoverflow.com/a/68643919/283366
axios.post("/translate-audio", fd)

Express

const multer  = require("multer")
const storage = multer.memoryStorage() // or use disk storage
const upload = multer({ storage })

app.post('/translate-audio', upload.single("audioFile"), async (req, res) => {
  console.log(req.file);
  // see https://github.com/expressjs/multer#file-information
});

Also, what is a good way to do this the other way around (sending audio blob from server to frontend)?

If you're working with files on disk, use res.sendFile(), otherwise res.send() is able to handle buffers.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • Thanks! Follow up question: Is there a way to only extract the file to buffer in memory instead of saving it in local disk?I'm working with small files that are at most a few hundred KB in size. – Michael Han Nov 11 '21 at 04:36
  • That's exactly what my answer does by using Multer's `memoryStorage()`. The file buffer will be in `req.file.buffer`. As per my answer, see https://github.com/expressjs/multer#file-information – Phil Nov 11 '21 at 04:43