nlobjFile.getValue does not work in Suitelet - netsuite

I have used the following code in a NetSuite Suitelet to upload and process a file:
function main(request,response){
if (request.getMethod() == 'GET'){
var form = nlapiCreateForm('Item Import Correction', false);
var fileField = form.addField('custpage_file', 'file', 'Select CSV');
form.addSubmitButton();
response.writePage(form);
}else{
try{
var file = request.getFile("custpage_file");
var content = file.getValue();//exception
response.write(content);
}catch(ex){
response.write('Exception:'+ex);
}
}
}
When I select a file and submit it, I get an exception on calling getValue() on nlobjFile. Here is the output of response:
Exception:JavaException: java.lang.NullPointerException: charsetName
However, I replace the getValue() call with some other method of the same object like getSize() or getType(), the code works fine.
I just want to parse a file selected by user in a Suitelet.

getFile() - Returns a file added through the nlobjForm.addField(name, type, label, sourceOrRadio, tab) method. When adding a file field type, you will set the type parameter of 'file'.
Make sure that the field you are referencing to using getFile() do exists in the form.

Calling the setEncoding() method on nlobjFile did the trick for me. I was using Chinese Encoding so this was the code that worked for me
var file = request.getFile("custpage_file");
file.setEncoding('GB18030');// Chinese
var content = file.getValue();//no exception

Related

How do I transfer rich text attachments from one document to another

I have 2 documents which are supposed work in such a way to be able to transfer files between them. However, it doesn't work. The exception I get is Exception occurred calling method NotesDocument.save() Notes error: One or more of the source document's attachment are missing. Run Fixup to delete the document in the source database. This happens after I try to call save() function on the document to which I've just transfered files from the first.
The functions are below:
function transferFiles(docToGetFrom, docToTransferTo, fileFieldFromFirstName, fileFieldFromSecondName)
{
var rit1:NotesRichTextItem = getFirstNotesRichTextItem(docToGetFrom, fileFieldFromFirstName);
docToTransferTo.copyItem(rit1, fileFieldFromSecondName);
deleteAllFilesFromDocument(docToGetFrom, fileFieldFromFirstName);
docToTransferTo.save();
}
function getFirstNotesRichTextItem(documentToGetFrom, fileFieldName)
{
if (documentToGetFrom == null)
{
return(null);
}
if (!documentToGetFrom.hasItem(fileFieldName))
{
return(null);
}
var rit1:NotesRichTextItem = documentToGetFrom.getFirstItem(fileFieldName);
return rit1;
}
function deleteAllFilesFromDocument(documentToDeleteFrom, fileFieldName)
{
var arr = getAllEmbeddedObjects(documentToDeleteFrom, fileFieldName);
for(var i = 0; i < arr.length; i++)
{
arr[i].remove();
}
documentToDeleteFrom.save();
}
function getAllEmbeddedObjects(documentToGetFrom, fileFieldName)
{
var rit1:NotesRichTextItem = getFirstNotesRichTextItem(documentToGetFrom, fileFieldName);
if (rit1 == null)
{
return(null);
}
try
{
var arr=rit1.getEmbeddedObjects();
return arr;
}
catch(e)
{
return(null);
}
}
According to plain logic, I need to do the following in order to make it work:
Get attachments from the document A
Copy them to the document B
Remove attachments from the document A
Call save() on A
Call save() on B
I did exactly the same, but nevertheless get this nasty exception. Also, I've tried to solve the problem by setting OLEDisableFX to 1, but with no luck. I assume that something must be wrong with the method copyItem() (I guess it can only work properly with simple datatypes). What's the problem? Thanks in advance.
You'll probably need to detach the attachment from the source document and attach it to the target document. See the NotesEmbeddedObject class for examples.
Use the CopyItemToDocument method of the NotesItem class. The following is some code I used in a LotusScript agent but the CopyItemToDocument method is also available in Java and SSJS.
If doc.Hasitem("RTF1") Then
Set item = Nothing
Set item = doc.getFirstItem("RTF1")
Call item.Copyitemtodocument(targetdoc, "targetRTF")
Call item.Remove()
End If

Hyperlink to open/download a File (Acumatica)

Is there any way to make a hyperlink to a file that will open its contents or download it from the table it belongs? (In a sense, do exactly the same thing as AllowEdit but open/download the file instead.) Example:
Where the Default Specification files are from files found on the customer:
Please note that what displays is the comment of the file. If anyone has any suggestions on how to display the file name instead, that would be appreciated as well.
You can get the filename like this:
UploadFileMaintenance uploadFileMaintenance = PXGraph.CreateInstance<UploadFileMaintenance>();
foreach (Guid note in PXNoteAttribute.GetFileNotes(cache, dacRecord))
{
FileInfo file = uploadFileMaintenance.GetFileWithNoData(note);
PXTrace.WriteInformation(file.Name);
}
To download the file, create a DAC field of string type. You can initialize the string to the file name in the FieldDefaulting or FieldSelecting event. Declare an Action and use the LinkCommand attribute in the ASPX file to make that field control a link.
In that Action event handler, you can redirect the browser to the file in order to download/open it:
UploadFileMaintenance uploadFileMaintenance = PXGraph.CreateInstance<UploadFileMaintenance>();
Guid[] notes = PXNoteAttribute.GetFileNotes(cache, dacRecord);
if (notes != null && notes.Length > 0)
{
FileInfo downloadFile = uploadFileMaintenance.GetFile(notes[0]);
if (downloadFile != null)
{
throw new PXRedirectToFileException(downloadFile.UID, true);
}
}

ServiceStack InMemoryVirtualPathProvider for Razor - GetViewPage null

I tested this with the default out of the box implementation and GetViewPage retrieves the view from the file system without a problem.
I swapped out the RazorFormat's VirtualFileSource for the inmemory one:
Plugins.Add(new RazorFormat() {
VirtualFileSources = new InMemoryVirtualPathProvider(this),
});
In the service I'm writing a view if it doesn't exist:
var helloView = razor.GetViewPage(email.BlastId.ToString());
if (helloView==null)
{
((InMemoryVirtualPathProvider)razor.VirtualFileSources)
.WriteFile("~/views/"+email.BlastId + ".cshtml", email.Blast);
// .WriteFile(email.BlastId + ".cshtml", email.Blast); doesn't work
}
helloView = razor.GetViewPage(email.BlastId.ToString());
//helloView is always null
I've confirmed that the RazorFormat's VirtualFileSource has the file, the GetViewPage just doesn't retrieve it.
Screenshot of the file located in the VirtualFileSource: https://db.tt/8oirKd9Msi
Furthermore this returns true: razor.VirtualFileSources.FileExists("~/views/"+email.BlastId + ".cshtml") I've tried it without the views folder/etc. It doesn't seem to make an impact.
The RazorFormat loads compiled views on Startup, so the view needs to exist in the VirtualFileSources before RazorFormat is registered in order for it to be available with GetViewPage().
To add a file after RazorFormat has loaded, you need to call AddPage() after it's written to the Virtual File System, e.g:
razorFormat.VirtualFileSources.WriteFile(filePath, contents);
var razorView = razorFormat.AddPage(filePath);
If you only wanted to create a temporary Razor View you can call CreatePage() to create the view:
var razorView = razorFormat.CreatePage(razorHtml);
And render it with:
razorFormat.RenderToHtml(razorView, model);
Or if both the Razor Page and model is temporary, it can be condensed in the 1-liner:
var html = razorFormat.CreateAndRenderToHtml(razorHtml, model);
Working Example
const string template = "This is my sample view, Hello #Model.Name!";
RazorFormat.VirtualFileSources.WriteFile("/Views/simple.cshtml", template);
var addedView = RazorFormat.AddPage("/Views/simple.cshtml");
var viewPage = RazorFormat.GetViewPage("simple"); //addedView == viewPage
var html = RazorFormat.RenderToHtml(viewPage, new { Name = "World" });
html.Print(); //= "This is my sample view, Hello World!"

Accessing data from inside html code to the main suitelet code

I have written an html code inside a suitelet and Within the script tags of this html I am calling data from another platform through an api call
Data is stored in a json format in a variable object called info.
How do I retrieve this 'info' value from inside the html code to the outside main suitelet code.
You need to put the information you want in an HTML tag then you put a code on your suitelet that will get all the parameter and you should be able to get that information:
funcntion suitelet(response, request){
if(request.getMethod() == 'GET') {
///render html whith textbox tag and with id=yourparamatername
}
else if(request.getMethod() == 'POST') {
var data = request.getParameter('yourparamatername');
}
}

Allow all file types to be selected in Extendscript's File object openDlg() method on MacOS

I am trying to get a reference to a File object using the File.openDlg() method using Extendscript, but when I do this it only seems to allow me to select a specific file type. I want the dialog to allow me to open any type of file. When I use File.openDialog() I am able to select any file type, but because I am launching the OS specific file chooser when a modal dialog button is clicked, it causes the open file chooser to keep popping up--I don't know why it keeps looping, but I suspect it has to do with the "modalness" of the dialog that is currently up when the method is called. So, I am left with simply using the File.openDlg() method, but I don't understand how to inform the MacOS to allow a user to select any file type.
In Adobe's documentation the signature for the .openDlg method is as follows:
fileObj.OpenDlg ([prompt][,filter][,multiSelect])
Then it specifies that the [filter] paramter is:
In Mac OS, a filter function that takes a File instance and returns true if the file
should be included in the display, false if it should not.
So, because I do not want any filetype masking I call the method like so:
newFootageSrc.openDlg("Select your file", function(file) {return true;}, false);
This doesn't work, so I found older Adobe documentation where this was specified for the [filter] param:
In Mac OS, a string containing the name of a function defined in the current
JavaScript scope that takes a File object argument. The function is called
foreach file about to be displayed in the dialog, and the file is displayed
only whenthe function returns true
So, I simply made a named function like this
function allFileTypesOSX(file){ return true; }
And then referenced allFileTypesOSX in the method call like this:
newFootageSrc.openDlg("Select your file", "allFileTypesOSX", false);
That didn't work, so I thought maybe just passing in the identifier itself rather than string would do the trick:
newFootageSrc.openDlg("Select your file", allFileTypesOSX, false);
But alas, that didn't work. Has anybody successfully been able to control file types in the MacOS dialog using ExtendScript?
I know I have this working in scripts at home, so I'll double check the syntax I use when I get home, but I do something along these lines (I'm supporting both windows and mac users).
var fileMask;
if(isWindows()) fileMask = '*.psd';
if(isMac()) fileMask = function(file){file.name.match(/\.psd$/i) ? true:false;}
var files = File.openDialog ('prompt', fileMask, true);
Its more similar to original attempt - you should be passing the actual filter function, not its name.
ETA: If you're not trying to actually limit the selectable files - have you tried just passing null, or leaving the parameter out altogether? They are all optional.
ETA: actual code from a working script (for Photoshop, works in CS3+). By 'works' I mean users on macs are able to select the files they need. I don't have a mac myself to actually see what they see. In a different script I found the following comment to myself above the isSupported function: 'returns true or false depending on if file is a png. 'Filter' doesn't seem to be working right on macs so this is a double check'. If the filter function isn't working as per the documentation this will definately be a problem for you when using the openDlg version of the method.
var filter;
if (isWindows()) {
filter = ["PNG:*.png"];
}
else {
filter = isSupported;
}
win.btnAdd.onClick = function() {
var f = File.openDialog("Open File", filter, false) ;
if (f == undefined)
return;
if (isSupported(f)) {
files = new Array();
files[0]=f;
win.lstImages.text = f.name;
methodInvoker.EnableControls();
} else {
alert("'" + decodeURI(f.name) + "' is an unsupported file.");
}
};
isSupported = function(file) {
try {
//macs will send a file or a folder through here. we need to respond true to folder to allow users to navigate through their directory structure
if (file instanceof Folder)
return true;
else
return file.name.match(/\.png$/i) != null;
} catch (e) {
alert("Error in isSupported method: " + e);
}
}

Resources