Create new folder without dialog using UXP

I’m probably overlooking something simple here. I just want to create a folder if it does not exist.

In CEP, all I have to do is

let outputFolder = app.Folder(outputFolderStr);
if (!outputFolder.exists) outputFolder.create();

How can I do this in UXP?

According to the storage APIs, I cannot see an obvious way to create a folder reference to a specific folder. All it says is:

// These require no user interaction:
const tempFolder = await fs.getTemporaryFolder();
const pluginFolder = await fs.getPluginFolder();  // read-only access to the plugin's install folder
const pluginDataFolder = await fs.getDataFolder();  // folder to store settings

// Display file/folder picker UI to access user files:
const userFolder = await fs.getFolder();  // folder picker

To provide some context, we have an in-house batch image converter tool built in CEP which I want to convert to UXP. Two of the fields are input and output folders which are saved as preferences. And the artists prefer to copy and paste the directories from file explorer rather than use folder pickers.

1 Like

The UXP file system is sandboxed, much like modern OSes are becoming. As such, beyond files in the plugin’s data, bundle, or temporary folder, users have to grant access explicitly to files. Once granted, you can convert these to persistent references (using createPersistentTokenEntry) and your user won’t need to be prompted again.

Access to folders will grant access to everything within, recursively. This means that for your purposes, you could ask for access to root volume(s) once, and then you’d have access to everything inside. You can use folder#getEntry(path) to use string-like paths to get access to specific locations.

Note that if you’re targeting the marketplace for distribution, you generally shouldn’t ask for the root volume. But if you’re doing this for a client or enterprise and aren’t going through the marketplace for delivery, this should work.

In the medium term, we’ll be adding Drag and Drop File support, meaning that you could have users drop a folder onto the panel, which would grant access as well. Longer term, we’ll look at adding a specific permission that grants full access automatically (again, not for marketplace plugins), but for now, the above is the best way forward.

1 Like

As Kerri mentioned, for enterprise purposes it appears that using localFileSystem.getFolder() to let the user pick your root drive folder and then storing that as a persistent token will give you full control of the harddrive, which will persist between sessions in most cases, is the best way to “remove” the permission restriction.

I do this by showing a pop up telling the user which folder to pick before showing the picker dialog.

From that point on, you must write a function to handle the creation of files in folders that don’t exist yet.

Once you have your root drive as a FileEntry, you can do this to get entries for any existing folder:
RootEntry.getEntry('path/to/existing/folder')
Since you cannot get an entry to a file that doesn’t exist, you must methodically move 1 folder at a time down your desired output path until you reach the point where the path does not exist yet. Then, you would ostensibly use the Entry.createFolder() to create each missing subfolder, culminating in a call of createFile() from that same doc page, and then after all that you would call the saveAs command for whichever format you are exporting to. require('photoshop').app.activeDocument.saveAs.jpg(fileEntry)

Would require("fs") module solve it these days? https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Modules/FileSystem/#mkdirpath-callback I think should work for PS but not XD.