Deleting file in Node.js
Asked Answered
F

2

16

I am using node in a Windows environment. When I use fs.unlinkSync(fileName), it seems to work. After the unlinkSync statement is executed, if I do a fs.existsSync(filename) it returns false indicating the file does not exists, but when I go to the physical drive I can still see the file.

At this point in time if I try and delete the file manually, it throws Access denied. However, the file is automatically removed from the file system only when I stop the executing node script file.

Is this the expected behavior?

Freshet answered 27/12, 2013 at 7:47 Comment(2)
I am pretty certain this is happening because the file is locked by Windows for some reason. That behavior is part of the DeleteFile SDK so there's not much Node.js can do about it.Reremouse
You'd need to show more code. If the file was opened and not closed properly, the unlink operation is queued to occur after the process exits.Solo
S
25

If the file has been opened and not closed within your NodeJS code, you'll encounter the behavior you're experiencing. It's behaving as expected, on Windows.

Take this code for example:

var fs = require('fs');

var filename = "D:\\temp\\temp.zip";
var tempFile = fs.openSync(filename, 'r');
// try commenting out the following line to see the different behavior
fs.closeSync(tempFile);

fs.unlinkSync(filename);

If the code uses openSync and then closeSync on the file, the file is immediately deleted when unlinkSync is called. If however, you were to remove the closeSync call, you'll find that the file is deleted only when the NodeJS process cleanly exits. This is just one example of a way to cause this problem to occur.

If you're using a third party library that is processing files, etc., it's possible the code is not properly closing the file handles/descriptors and you would also encounter this issue (for the same reason).

FYI: The file will appear to be deleted immediately if you test this code on a Linux based operating system. It's a difference in behavior between the operating systems and the way files are deleted.

Details

When NodeJS on Windows deletes a file, it's actually not calling an API to directly delete a file. Instead, it's using a low level function called ZwSetInformation (reference). With that function, it's setting a field called DeleteFile to TRUE for the specified file (handle). That's used so that when all file handles are closed for that file, it will be automatically deleted. Files in NodeJS are opened with the access mode of FILE_SHARE_DELETE so that they can be deleted properly by use of the other function.

Solo answered 27/12, 2013 at 13:45 Comment(2)
Thanks ... missing the closeSync function call. Thanks a ton.Freshet
This still didn't work for me. I'm still getting the hidden lock file even after the fs.closeSync / fs.unlinkSync. The files are still in windows explorer but any attempt to delete them requires local admin rights by none other than myself.Rattray
S
0

I had similar problem when I was using this to create a new file

lib.create = function (directory, fileName, data) {
  return fs.promises.open(`${lib.baseDir}${directory}/${fileName}.json`, "wx")
    .then(fileHandle => {
      // Convert data to string
      const stringData = JSON.stringify(data);

      return fileHandle.writeFile(stringData)
        .then(() => Promise.resolve(`File '${fileName}.json' saved successfully`))
        .catch(() => Promise.reject("Error writing to new file"));
    })
    .catch(() => Promise.reject("Could not create new file, it may already exist"));
}; 

and this to delete file

lib.delete = function (directory, fileName) {
  return fs.promises.unlink(`${lib.baseDir}${directory}/${fileName}.json`)
    .then(() => Promise.resolve(`File '${fileName}.json' deleted successfully`))
    .catch(() => Promise.reject(`Error deleting a ${fileName}.json`))
};

my file was deleted after killing node app. The reason is that

fileHandle.writeFile

dosen't close the file automatically and what needs to be done is

fileHandle.writeFile

returns a Promise so we can add another then and there close the file

return fileHandle.writeFile(stringData)
   .then(() => fileHandle.close())
      .then(() => Promise.resolve(`File '${fileName}.json' saved successfully`))
   .catch(() => Promise.reject("Error writing to new file"));

now my delete works good!

Sprag answered 5/4, 2021 at 12:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.