- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yesterday
While sending attachment in e-bonding duplicate attachments are created in test instance.
Below is code : - Help to get it sorted !!
(function executeRule(current, previous /*null when async*/) {
try {
var gsa = new GlideSysAttachment();
var content = "Sample troubleshooting steps\nLine 1\nLine 2";
var bytes = new Packages.java.lang.String(content).getBytes("UTF-8");
gsa.write('incident', current.sys_id, 'Troubleshooting.txt', 'text/plain', bytes);
} catch (e) {
gs.error('failed: ' + e);
}
})(current, previous);
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yesterday
Hi @SandeepKSingh
For your code .. below will help !! and explained in video:
Approach
-
Compute a checksum of the new content.
-
Look for existing attachments on that record with the same filename and checksum.
-
Only write when it is truly new.
2.1 Script Include
Create a Script Include AttachmentDedupUtil
(Accessible from all apps).
var AttachmentDedupUtil = Class.create();
AttachmentDedupUtil.prototype = {
initialize: function() {},
// Compute SHA-256 of a Java byte[] or String
_sha256: function(bytesOrString) {
var MessageDigest = Packages.java.security.MessageDigest;
var StandardCharsets = Packages.java.nio.charset.StandardCharsets;
var md = MessageDigest.getInstance("SHA-256");
var bytes = bytesOrString;
if (typeof bytesOrString === 'string') {
bytes = new Packages.java.lang.String(bytesOrString).getBytes(StandardCharsets.UTF_8);
}
var digest = md.digest(bytes);
// Hex encode
var sb = new Packages.java.lang.StringBuilder();
for (var i = 0; i < digest.length; i++) {
var b = digest[i];
var hex = java.lang.Integer.toHexString((b & 0xff) | 0x100).substring(1);
sb.append(hex);
}
return sb.toString(); // hex string
},
// Return hex hash for an attachment record (by sys_id)
_hashAttachment: function(sysAttachmentGR) {
var gsa = new GlideSysAttachment();
var contentStr = gsa.getContent(sysAttachmentGR); // returns String
return this._sha256(contentStr);
},
// Check if an attachment with same filename and content already exists on the target record
existsOnRecord: function(tableName, recordSysId, fileName, contentStrOrBytes) {
var targetHash = this._sha256(contentStrOrBytes);
var att = new GlideRecord('sys_attachment');
att.addQuery('table_name', tableName);
att.addQuery('table_sys_id', recordSysId);
att.addQuery('file_name', fileName);
att.query();
while (att.next()) {
try {
var existingHash = this._hashAttachment(att);
if (existingHash == targetHash)
return true; // exact same content already present
} catch (e) {
gs.warn('Hash compare failed for attachment ' + att.sys_id + ': ' + e);
}
}
return false;
},
// Ensure an attachment exists exactly once. Returns sys_id if created, null if skipped.
ensureOnce: function(tableName, recordSysId, fileName, contentType, contentStrOrBytes) {
if (this.existsOnRecord(tableName, recordSysId, fileName, contentStrOrBytes)) {
return null; // duplicate found, skip
}
var gsa = new GlideSysAttachment();
// Accept either String or Java byte[]
var bytes = contentStrOrBytes;
if (typeof contentStrOrBytes === 'string') {
bytes = new Packages.java.lang.String(contentStrOrBytes).getBytes("UTF-8");
}
return gsa.write(tableName, recordSysId, fileName, contentType, bytes);
},
type: 'AttachmentDedupUtil'
};
2.2 Fixed Business Rule
Table: incident
When: after
update
Condition: add a guard to run only when relevant (example: when a specific field changes).
// Name: FIXED - Attach only if new
(function executeRule(current, previous /*null when async*/) {
// Example guard so it does not run on every minor change
if (current.u_generate_note == true && previous.u_generate_note != true) {
try {
var content = "Sample troubleshooting steps\nLine 1\nLine 2";
var util = new AttachmentDedupUtil();
var createdId = util.ensureOnce(
'incident',
current.sys_id,
'Troubleshooting.txt',
'text/plain',
content // can also pass a Java byte[] if you have binary
);
if (createdId)
gs.info('Attachment created: ' + createdId);
else
gs.info('Skipped duplicate attachment for ' + current.number);
} catch (e) {
gs.error('FIXED BR failed: ' + e);
}
}
})(current, previous);
If you found my response helpful, I would greatly appreciate it if you could mark it as "Accepted Solution" and "Helpful."
Your support not only benefits the community but also encourages me to continue assisting. Thank you so much!
Thanks and Regards
Ravi Gaurav | ServiceNow MVP 2025,2024 | ServiceNow Practice Lead | Solution Architect
CGI
M.Tech in Data Science & AI
YouTube: https://www.youtube.com/@learnservicenowwithravi
LinkedIn: https://www.linkedin.com/in/ravi-gaurav-a67542aa/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yesterday
You can check the below video that will help you to understand the logic:
https://www.youtube.com/watch?v=ztZSdCy1CRw&list=PLKH9bPqlw1neHQZWQpYXHKy7LGiG9lhZn&index=9
If you found my response helpful, I would greatly appreciate it if you could mark it as "Accepted Solution" and "Helpful."
Your support not only benefits the community but also encourages me to continue assisting. Thank you so much!
Thanks and Regards
Ravi Gaurav | ServiceNow MVP 2025,2024 | ServiceNow Practice Lead | Solution Architect
CGI
M.Tech in Data Science & AI
YouTube: https://www.youtube.com/@learnservicenowwithravi
LinkedIn: https://www.linkedin.com/in/ravi-gaurav-a67542aa/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yesterday
Hi @SandeepKSingh
For your code .. below will help !! and explained in video:
Approach
-
Compute a checksum of the new content.
-
Look for existing attachments on that record with the same filename and checksum.
-
Only write when it is truly new.
2.1 Script Include
Create a Script Include AttachmentDedupUtil
(Accessible from all apps).
var AttachmentDedupUtil = Class.create();
AttachmentDedupUtil.prototype = {
initialize: function() {},
// Compute SHA-256 of a Java byte[] or String
_sha256: function(bytesOrString) {
var MessageDigest = Packages.java.security.MessageDigest;
var StandardCharsets = Packages.java.nio.charset.StandardCharsets;
var md = MessageDigest.getInstance("SHA-256");
var bytes = bytesOrString;
if (typeof bytesOrString === 'string') {
bytes = new Packages.java.lang.String(bytesOrString).getBytes(StandardCharsets.UTF_8);
}
var digest = md.digest(bytes);
// Hex encode
var sb = new Packages.java.lang.StringBuilder();
for (var i = 0; i < digest.length; i++) {
var b = digest[i];
var hex = java.lang.Integer.toHexString((b & 0xff) | 0x100).substring(1);
sb.append(hex);
}
return sb.toString(); // hex string
},
// Return hex hash for an attachment record (by sys_id)
_hashAttachment: function(sysAttachmentGR) {
var gsa = new GlideSysAttachment();
var contentStr = gsa.getContent(sysAttachmentGR); // returns String
return this._sha256(contentStr);
},
// Check if an attachment with same filename and content already exists on the target record
existsOnRecord: function(tableName, recordSysId, fileName, contentStrOrBytes) {
var targetHash = this._sha256(contentStrOrBytes);
var att = new GlideRecord('sys_attachment');
att.addQuery('table_name', tableName);
att.addQuery('table_sys_id', recordSysId);
att.addQuery('file_name', fileName);
att.query();
while (att.next()) {
try {
var existingHash = this._hashAttachment(att);
if (existingHash == targetHash)
return true; // exact same content already present
} catch (e) {
gs.warn('Hash compare failed for attachment ' + att.sys_id + ': ' + e);
}
}
return false;
},
// Ensure an attachment exists exactly once. Returns sys_id if created, null if skipped.
ensureOnce: function(tableName, recordSysId, fileName, contentType, contentStrOrBytes) {
if (this.existsOnRecord(tableName, recordSysId, fileName, contentStrOrBytes)) {
return null; // duplicate found, skip
}
var gsa = new GlideSysAttachment();
// Accept either String or Java byte[]
var bytes = contentStrOrBytes;
if (typeof contentStrOrBytes === 'string') {
bytes = new Packages.java.lang.String(contentStrOrBytes).getBytes("UTF-8");
}
return gsa.write(tableName, recordSysId, fileName, contentType, bytes);
},
type: 'AttachmentDedupUtil'
};
2.2 Fixed Business Rule
Table: incident
When: after
update
Condition: add a guard to run only when relevant (example: when a specific field changes).
// Name: FIXED - Attach only if new
(function executeRule(current, previous /*null when async*/) {
// Example guard so it does not run on every minor change
if (current.u_generate_note == true && previous.u_generate_note != true) {
try {
var content = "Sample troubleshooting steps\nLine 1\nLine 2";
var util = new AttachmentDedupUtil();
var createdId = util.ensureOnce(
'incident',
current.sys_id,
'Troubleshooting.txt',
'text/plain',
content // can also pass a Java byte[] if you have binary
);
if (createdId)
gs.info('Attachment created: ' + createdId);
else
gs.info('Skipped duplicate attachment for ' + current.number);
} catch (e) {
gs.error('FIXED BR failed: ' + e);
}
}
})(current, previous);
If you found my response helpful, I would greatly appreciate it if you could mark it as "Accepted Solution" and "Helpful."
Your support not only benefits the community but also encourages me to continue assisting. Thank you so much!
Thanks and Regards
Ravi Gaurav | ServiceNow MVP 2025,2024 | ServiceNow Practice Lead | Solution Architect
CGI
M.Tech in Data Science & AI
YouTube: https://www.youtube.com/@learnservicenowwithravi
LinkedIn: https://www.linkedin.com/in/ravi-gaurav-a67542aa/
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
yesterday
Thanks for the quick Help