NetSuite SuiteScript to modify file in the file cabinet - netsuite

We have files within the NetSuite file cabient which need to be updated (the url field has changed). I found the noted article on this site but there is no code example to perform the requested. It indicates to use the nlapiLoadFile and nlapiSubmitFile calls; would anyone be able to assist with a code example?
Link:
Can Netsuite Suitescript modify a file in the file cabinet?

Ya, it seems a bit odd. The only way I found is:
Load The File
Create a file handle with:
Set the file name to one that you intended.
Set the content to intended one
Set the folder and submit.
I have attached a code snippet
var file = nlapiLoadFile(file_id);
var content = file.getValue();
content = '...put your content...';
file = nlapiCreateFile(file.getName(), 'FILE TYPE', content);
file.setFolder(required_folder_id);
nlapiSubmitFile(file);
Hope this helps.

There is no special API function to edit an existing file, you could take the details of the existing file and create a new file with the same details but changing the data field only and deleting the old file.
var start = function(request, response)
{
var fileId = "107524";//get the existing file id
var file = nlapiLoadFile(fileId);
var data = file.getValue();
var name = file.getName();
var folderId = file.getFolder();
var fileType = file.getType();
nlapiDeleteFile(fileId);//delete the older file
data += ",this is the appended data";//change the data
var newFile = nlapiCreateFile(name, fileType, data);//create a new file with the same details
newFile.setFolder(folderId);
nlapiSubmitFile(newFile);//submit it
}

Do you mean file instead of field? If you use nlapiLoadFile(/path/file), you can then use getURL() to provide a link to that file.

NetSuite does not have a edit file kind of an API. You will have to load the original file, modify the contents as per your needs and then submit that data by creating a new file with same file name and inside the same folder. This simply overrides the existing file.
Here's the code sample:
var original = nlapiLoadFile(FILE_ID_OR_FILE_PATH_IN_FILE_CABINET);
var originalContent = original.getValue(); //Return the value (base64 encoded for binary types) of the file
var updated = nlapiCreateFile(original.getName(), FILE_TYPE, UPDATED_FILE_CONTENTS);
updated.setFolder(original.getFolder());
nlapiSubmitFile(updated);

I experienced a similar error when trying to modify a file using SuiteScript in Netsuite at the server-side. I was using the way explained in the documentation, where they say copying a new file through file.copy() with conflictResolution: file.ConflictResolution.OVERWRITE. However, that way didn't work for me as it neither created the file nor overwrote it. Finally, I use the following form to get it working:
...
let fileNew = file.create({
name: 'same_name_of_the_original_file',
fileType: file.Type.PLAINTEXT, // change it depending the file type you will create
contents: credentials.body,
});
fileNew.folder = folder_id;
let fileId = fileNew.save();
...
So, the key is to change the folder and saving it after the file is created. After that, saving the file would overwrite the original.

Related

Is there a way to use fs to add data to json object

i have a question about something i wanna do with fs, its updating a pice of data inside a json object so like
"links": ["https://google.com/", "https://youtube.com/"]
}
Then after youtube i could write a program that i can use to add another link inside the the links object. So say i wanted to add instagram to the list i would run that program instead. (this is in the sence of that im working on a discord bot so it would add the arguments to the list but you get the point) Is this possible somehow? Kinda like a update where it just adds another link.
For example the json is in a file called youtube-links.json
First we read the data like so const readFile = fs.readFileSync('youtube-links.json')
Convert to string const cleanData = readFile.toString()
Then parse the JSON file const linksFromFIle = JSON.parse(cleanData)
After that we push new data to it
linksFRomFIle.push({
links: ["new string"]
})
Then save the new file by overwriting it with the new data

cucumber hook scenario.embed always create screenshot at project root

In cucumber hook scenario.embed always create screenshot at my project root directory. I need it to create it different location
scenario.embed(screenshot, "image/png");
I create below code still no wayout:
File screenShot=((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
// extracting date for folder name.
SimpleDateFormat dateFormatForFoldername = new SimpleDateFormat("yyyy-MM-dd");//dd/MM/yyyy
Date currentDate = new Date();
String folderDateFormat = dateFormatForFoldername.format(currentDate);
// extracting date and time for snapshot file
SimpleDateFormat dateFormatForFileName = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss");//dd/MM/yyyy
String fileDateFormet = dateFormatForFileName.format(currentDate);
String filefolder="./ScreenShots"+"/FailCase/"+folderDateFormat+"/";
// Creating folders and files
File screenshot = new File(filefolder+fileDateFormet+".jpeg");
FileUtils.copyFile(screenShot, new File(screenshot.getPath()));
byte[] fileContent = Files.readAllBytes(screenshot.toPath());
scenario.embed(fileContent, "image/png");
How to pass a directory path to embed funtion or override it?
#mpkorstanje - he is rightly pointed about it
As per his comment:
Use OutputType.BYTES and send the bytes directly to scenario.embed and write them directly to the screenshot file
But my issue was I am using mkolisnyk package and when I am using #AfterSuite annotation of it, it creating fail file images over root folder. seems bug in mkolisnyk package.
Mixing AfterSuite of testng and #ExtendedCucumberOptions of mkolisnyk works for me

Getting document attachments using Kentico API

I created book store site on Kentico i used only their adminstration and display the data from my website using Kentico API's but am strugled in getting attachment files related to specific document i've got document data with no problem using
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);
var documents = tree.SelectNodes("CMS.Product");
need also to get related attachment files like book PDFs.. i've tried to use
DocumentAttachment
AttachmentInfo
AttachmentInfoProvider
classes but i couldn't get the data .. I would appreciate if any one help me in that.
Actually am searching about something like GetAttachment().Where("AttachmentFile","Ënglish File")
You can filter the returned attachments based on their values in columns (CMS_Attachment table) by using a code like this:
var attachment = AttachmentInfoProvider.GetAttachments()
.WhereEquals("AttachmentName", "Englishfile")
.And()
.WhereEquals("AttachmentExtension", "jpg")
.TopN(1)
.FirstOrDefault();
if (attachment != null)
{
// attachment was found
}
This code will get one .jpg file where attachment name equals to "EnglishFile"
Solved after using something like
var Attachment = AttachmentInfoProvider.GetAttachments(226, true);
This is from Kentico documentation. This example shows how to add an attachment and modify its metadata. You can ignore that part.You will have to make it generic to work for all examples.
Kentico 9 API Links
// Creates a new instance of the Tree provider
TreeProvider tree = new TreeProvider(MembershipContext.AuthenticatedUser);
// Gets a page
TreeNode page = tree.SelectSingleNode(SiteContext.CurrentSiteName, "/Articles", "en-us");
if (page != null)
{
// Gets an attachment by file name
AttachmentInfo attachment = DocumentHelper.GetAttachment(page, "file.png", tree);
// Edits the attachment's metadata (name, title and description)
attachment.AttachmentName += " - modified";
attachment.AttachmentTitle = "Attachment title";
attachment.AttachmentDescription = "Attachment description.";
// Ensures that the attachment can be updated without supplying its binary data
attachment.AllowPartialUpdate = true;
// Saves the modified attachment into the database
AttachmentInfoProvider.SetAttachmentInfo(attachment);
}

How to use Node.js to create modified versions of html documents?

I am trying to do this:
Read html document "myDocument.html" with Node
Insert contents of another html document named "foo.html" immediately after the open body tag of myDocument.html.
Insert contents of yet another html document named "bar.html" immediately before the close body tag of myDocument.html.
Save the modified version of "myDocument.html".
To do the above, I would need to search the DOM with Node to find the open and closing body tags.
How can this be done?
Very simply, you can use the native Filesystem module that comes with Node.JS. (var fs = require("fs")). This allows you to read and convert the HTML to a string, perform string replace functions, and finally save the file again by rewriting it.
The advantage is that this solution is completely native, and requires no external libraries. It is also completely faithful to the original HTML file.
//Starts reading the file and converts to string.
fs.readFile('myDocument.html', function (err, myDocData) {
fs.readFile('foo.html', function (err, fooData) { //reads foo file
myDocData.replace(/\<body\>/, "<body>" + fooData); //adds foo file to HTML
fs.readFile('bar.html', function (err, barData) { //reads bar file
myDocData.replace(/\<\/body\>/, barData + "</body>"); //adds bar file to HTML
fs.writeFile('myDocumentNew.html', myDocData, function (err) {}); //writes new file.
});
});
});
In a simple but not accurate way, you can do this:
str = str.replace(/(<body.*?>)/i, "$1"+read('foo.html'));
str = str.replace(/(<\/body>)/i, read('bar.html')+'$1');
It will not work if the myDocument content contains multiple "<body ..' or '</body>', e.g. in javascript, and also the foo.html and bar.html can not contains '$1' or '$2'...
If you can edit the content of myDocument, then you can leave some "placeholder" there(as html comments), like
<!--foo.html-->
Then, it's easy, just replace this "placeholder" .
Use the cheerio library, which has a simplified jQuery-ish API.
var cheerio = require('cheerio');
var dom = cheerio(myDocumentHTMLString);
dom('body').prepend(fooHTMLString);
dom('body').append(barHTMLString);
var finalHTML = dom.html();
And just to be clear since the legions of pro-regex individuals are already appearing in droves, yes you need a real parser. No you cannot use a regular expression. Read Stackoverflow lead developer Jeff Atwood's post on parsing HTML the Cthulhu way.

Saving per-user or per-document preferences in a Photoshop script

I'm working on a Photoshop script in JavaScript using ExtendScript. My script allows some user input, and I'd like to save it between uses. That is, I'm looking for a way to save a simple string or numeric value under a particular key so that I'll be able to access it on subsequent uses of the script. Simply put, I want to save a preference for my script. How do I do that?
Even better would be to be able to save at least some preferences on a per-document basis. Is that possible? That is, can I store an arbitrary bit of data with a document?
You can use put/get custom options to save preference parameters that persist across Photoshop launches:
const kMyFlag = app.stringIDToTypeID( "myFlag" );
const kMyNumber = app.stringIDToTypeID( "myNumber" );
const kMySettings = "mySettings";
function saveSettings()
{
var desc = new ActionDescriptor();
desc.putBoolean(kMyFlag, true);
desc.putInteger(kMyNumber, 42);
// "true" means setting persists across Photoshop launches.
app.putCustomOptions( kMySettings, desc, true );
}
function getSettings()
{
var desc = app.getCustomOptions( kMySettings );
return [desc.getBoolean( kMyFlag ), desc.getInteger( kMyNumber )];
}
You have some options. You can create a text file and write to it using the File object:
var prefs = new File("~/desktop/prefs.txt");
prefs.open("w"); // or "a" to append
prefs.writeln("user:lenny;favorite_color:ff6600;likes:sunsets;");
...if you wanted your preferences tied to the script itself.
If you want per-document preferences you could write a string to one of the metadata fields of the file your working on using Document.info like this (using the 'instructions' field but you could use any writable field):
var doc = app.activeDocument;
doc.info.instructions = "user:lenny;favorite_color:ff6600;likes:sunsets;";
//alert(doc.info.instructions); // see, it works!
As for how to actually format the string you could just do it like a simple config file or, if you have a complex user preferences object you could use the XML object to construct and serialize it. JSON would be great for this but there is no JSON object in Extendscript, unfortunately.
For per-document prefs I suggest the use of the XMP Metadata. You can find example snippet here: http://forums.adobe.com/thread/790973. You can leverage AdobeXMPScript library to create your own namespace like it is suggested in the link by Paul Riggott.

Resources