The CreatorCon Call for Content is officially open! Get started here.

Duplicate attachment!!

SandeepKSingh
Kilo Sage

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);

 

1 ACCEPTED SOLUTION

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/

View solution in original post

3 REPLIES 3

Ravi Gaurav
Giga Sage
Giga Sage

Hi @SandeepKSingh 

 

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/
Hi Youtube Family, I am Ravi Gaurav. I am Expert in ServiceNow . Welcome to my youtube channel. If you guys enjoyed it, make sure to Like👍 , Comment💬 and Subscribe❤️ _________________________________________ Copyright Disclaimer : All Rights to VideoLabel Co. & No Copyright infringement intende...

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/

SandeepKSingh
Kilo Sage

Thanks for the quick Help