How to save a file when the checkbox is enabled Ignore "save as" commands

Hello, I have a question about saving files in the system.

I did it like this:

const tempFolder = await localFileSystem.getTemporaryFolder();

const file = await tempFolder.createFile(`test.png`, {
 overwrite: true,
});

await currentDocument.saveAs.png(
 file,
 { compression: 1 },
 true,
);

const arrayBuffer = await file.read({
 format: storage.formats.binary,
});

But there is a problem:
When I try to run my plugin in batch processing to process an entire folder of photos, the Ignore “save as” commands checkbox disables my saveAs method. After which the buffer reading method cannot read the file, since it actually does not exist.

I thought that this checkbox would only block pop-ups about saving a file, so my entire script was built without them, but this is not the case and it blocks background saving as well

I read a large number of topics about working with files on this form, read a couple of books on UXP development, but I never found an answer to how I can get around this.

In addition: I know about API imaging, these methods will raise the minimum version for my plugin, it might be possible to do this with it, but this is probably a last resort

To clarify: you have recorded your plugin into an Action (with recordAction).
Running that Action with the Batch dialog (thanks for the image), results in those saveAs calls being nullified.

That is interesting. I’ll log the issue to see how those calls are intercepted.

To ensure the file creation and writing process is not interrupted by the checkbox settings you have to use a different approach for file handling Instead of using “saveAs”, consider directly writing to the file system if possible.

const { localFileSystem, storage } = require('uxp').storage;
const { app } = require('photoshop');

async function saveFileAsPNG(fileName, imageData) {
    try {
        const tempFolder = await localFileSystem.getTemporaryFolder();
        const file = await tempFolder.createFile(fileName, { overwrite: true });

        // Write image data directly to the file
        await file.write(imageData, { format: storage.formats.binary });

        console.log(`File saved successfully: ${file.nativePath}`);
        return file;
    } catch (error) {
        console.error('Error saving file:', error);
        throw error;
    }
}

async function processImagesInBatch(imageFolder) {
    try {
        const entries = await imageFolder.getEntries();
        for (const entry of entries) {
            if (entry.isFile && entry.name.endsWith('.png')) {
                const imageData = await processImage(entry);

                if (imageData) {
                    // Save the processed image
                    await saveFileAsPNG(entry.name, imageData);
                }
            }
        }
    } catch (error) {
        console.error('Error processing images:', error);
    }
}

async function processImage(file) {
    try {
        // Open the file in Photoshop
        const document = await app.open(file);
        
        // Perform any necessary image processing here
        // For example, apply some filters or adjustments

        // Export the document as PNG to an array buffer
        const arrayBuffer = await document.saveTo.arrayBuffer({ format: storage.formats.binary });
        
        // Close the document without saving
        await document.closeWithoutSaving();
        
        return arrayBuffer;
    } catch (error) {
        console.error('Error processing image:', error);
        return null;
    }
}

// Example usage:
(async () => {
    try {
        const imageFolder = await localFileSystem.getFolder();
        await processImagesInBatch(imageFolder);
    } catch (error) {
        console.error('Error initializing batch processing:', error);
    }
});

Let me know if it works !

Yes, I am developing a plugin for react and actions when processing starts, I write it into the action, then it appears in batch processing and calls the plugin with its current settings.

P.S. screenshot for clarityи

Thanks for the example!

I see that it calls the getFolder method, I would like the plugin not to call any modal windows, since it already works with batch processing in which photos are specified

But I saw some interesting methods like document.saveTo.arrayBuffer

I will carefully study your code and try to adapt it for myself, I will answer immediately after the tests, thanks

1 Like

This code is not suitable for package processing, as it causes the getFolder method, and it is not needed in the package processing, because the user has already chosen the folder

Without this method, it is impossible to do it since the problem is the same, saveAs does not work, and without it I can’t get a file to read the arrayBuffer out of it

This will work if I start processing the folder without package processing, in a separate button in my plugin

The basic usage of Override Action "Save As" Commands is to combine it with Destination: Folder and specify the destination on the action side. It has no effect to block pop-ups about saving a file.

Maybe the assumption in your question is wrong?

Perhaps I touched on some wrong question, but the main idea is that the saveAs method is disabled when this checkbox is enabled.

Because of this, the file is not created and then I cannot read it - this is the main problem

@Sem
Perhaps that is the intended behavior of Photoshop, so failure is the expected result. Or is the main concept of your plugin to be able to specify the destination on the action side using that setting?

If not, it would be faster to change the concept.

If yes, then there needs to be a way for it to work regardless of the Override Action "Save As" Commands setting.

Not sure if it would be successful, but how about the following candidate?

  • Save with your own recorded batchPlay instead of saveAs
  • Use another type of command such as Generator, Quick Export, etc.
  • Execute ExtendScript with action calls, or open commands, etc.
  • Raise to a version where fs module and imaging are available

I think I’ll do my own packet processing in the plugin, where the user will select a folder with photos, and then I’ll process them in a loop just like I do with one

But I would be interested to see these options, could you show an example or links to documentation on how I could do this?

  • Save with your own recorded batchPlay instead of saveAs
  • Use another type of command such as Generator, Quick Export, etc.

Thank you

@Sem
Basically, both use some function to generate the Action Descriptor, and then execute it via batchPlay.

Record the save or export actions with the following functions.

UXP Plugin:

Photoshop:

  • Plugins > Development > Record Action Commands…
  • Actions Panel > Copy as JavaScript

@sttk3
Sorry, but I don’t think Export As or Quick Export is available?
image

This is what I got from:

  • Plugins > Development > Record Action Commands…
  • Yes the Action Record is the same

The Export Layer is the main thing I even started to make my Plugin. Now it’s just empty. :frowning:

The main point is to find and record another means of saving that is not inhibited by the Override Action "Save As" Commands setting.

I do not guarantee that the items in the example will work reliably, nor do I guarantee that a means exists that will work reliably.

The next suggestion is to generate files with imaging and fs, and if that is not possible, it is possible to find another way or change the concept.

Since I didn’t find a way to bypass this flag, I decided to make my own batch processing implementation.

The user, by clicking on the button in the plugin, will select a folder with photos, where I will process them in a loop, just like I did for regular processing

The only thing is that I will have to implement some of the functionality myself, for example:

  • whether to process subfolders
  • in what format to save the result
    and maybe in the future I’ll make a choice of a place to save

Let me know if you find out anything or find out solutions for this, but for now I will have to write my own implementation of batch processing directly inside the plugin, as I described above

Thank you