0

I am trying to write a number of files in node to a specific folder, but I am having some issues when creating the folder:

I got an upload.js file that recieves two files from the front end, then I am using an async for loop not to block the event loop, and I have a function that I run for each file it receives, this funtion checks if the folder exists and if not it creates it:

import Router from 'express'
import multer from 'multer'
import { resolve } from 'path'
import { constants } from 'fs'
import { writeFile, mkdir, access } from 'fs/promises'

async function asyncForEach(array, callback) {
  for (let i = 0, j = array.length; i < j; i++) {
    await callback(array[i], i, array)
  }
}

router.put('/', upload.array('files', 5), async (req, res) => {
  const { files } = req

  const temporalFolder = `./tmp`

  const writeToFolder = async (name, file) => {
    try {
      await access(temporalFolder, constants.R_OK | constants.W_OK)
    } catch (error) {
      await mkdir(temporalFolder)
    } finally {
      await writeFile(resolve(temporalFolder, name), file)
    }
  }

  await asyncForEach(files, async (file) => { 
    const { originalname, buffer } = file
    writeToFolder(originalname, buffer)
  }

  res.end()
})

export default router

If the folder is already created I get no error and it works fine, but the first time when the folder does not exist I get this even thou all works:

[Error: EEXIST: file already exists, mkdir './tmp'] {
   errno: -17,
   code: 'EEXIST',
   syscall: 'mkdir',
   path: './tmp'
}

Update: Thanks to Rajdeep Debnath I fixed it with this:

const writeToFolder = async (name, file) => {
  try {
    await access(temporalFolder, constants.R_OK | constants.W_OK)
  } catch (error) {
    await mkdir(temporalFolder, { recursive: true })
  } finally {
    await writeFile(resolve(temporalFolder, name), file)
  }
}
5
  • Not a direct answer on why this happens, but I'd suggest to move the check if the targetfolder exists from within writeToFolder to be executed before the asyncForEach. There's no need to check the existance of the folder again for every file to be written... Commented Jul 26, 2021 at 15:06
  • The reson for this is that I am doing some validations before writing, so if the validation fails I dont want to create the folder in the first place Commented Jul 26, 2021 at 15:08
  • Is there any possibility that these validations are in the same block as await access(...) and one of them throws an error? Because if that's the case, it will go into the catch block and try to create the directory, even if access didn't throw an error ... Just add a console.log(error) right before await mkdir(...) to see, what error was thrown, to cause the catch to be executed Commented Jul 26, 2021 at 15:15
  • No, the validations are in the for loop, and only attempts to create the dir and write file if there are no errors Commented Jul 26, 2021 at 15:20
  • In regard to usage of access, could it be related to the Race Condition referred in that Func's documentation? "Using fsPromises.access() to check for the accessibility of a file before calling fsPromises.open() is not recommended. Doing so introduces a race condition, since other processes may change the file's state between the two calls. Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible." ref: nodejs.org/api/fs.html#fs_fspromises_access_path_mode Commented Jul 26, 2021 at 15:34

1 Answer 1

2

Calling fs.promises.mkdir() when path is a directory that exists results in an error only when recursive is false. So you need to pass {recursive:true} as the second option

const writeToFolder = async (name, file) => {
  try {
    await mkdir(temporalFolder, {recursive:true})
    await writeFile(resolve(temporalFolder, name), file)
  } catch (error) {
Sign up to request clarification or add additional context in comments.

1 Comment

Actually the recursive: true helped just not the way you are using in the example, I basically used the same example as the one above using access, ansd using mkdir with recursive: true and no errors now. I have edited the final solution and giving you the Accepted answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.