← Script library

Script Includes

Summarize Attachment Storage for a Record

Return the attachment count and total file size in bytes for one record using metadata only, without reading file contents or changing records.

JavaScript
var AttachmentStorageUtil = Class.create();
AttachmentStorageUtil.prototype = {
  initialize: function() {},

  // Server-only metadata query. This is not an ACL authorization check.
  // Returns {ok, count, bytes, error}; failed results must not be used as totals.
  summarize: function(tableName, recordId) {
    var result = {ok: false, count: 0, bytes: 0, error: ''};
    if (typeof tableName !== 'string' || !/^[a-zA-Z0-9_]+$/.test(tableName) ||
        typeof recordId !== 'string' || !/^[a-fA-F0-9]{32}$/.test(recordId)) {
      result.error = 'Supply an internal table name and a 32-character record sys_id.';
      return result;
    }

    try {
      var attachments = new GlideAggregate('sys_attachment');
      attachments.addQuery('table_name', tableName);
      attachments.addQuery('table_sys_id', recordId.toLowerCase());
      attachments.addAggregate('COUNT');
      attachments.addAggregate('SUM', 'size_bytes');
      attachments.setGroup(false);
      attachments.query();
      if (attachments.next()) {
        result.count = parseInt(attachments.getAggregate('COUNT'), 10) || 0;
        result.bytes = parseInt(attachments.getAggregate('SUM', 'size_bytes'), 10) || 0;
      }
      result.ok = true;
    } catch (error) {
      gs.error('[SN-Tricks:AttachmentStorageUtil] Metadata query failed: ' + error);
      result.error = 'Attachment metadata query failed; check the system log.';
    }
    return result;
  },

  type: 'AttachmentStorageUtil'
};

How to use it

1. Create an active Script Include in Global scope named AttachmentStorageUtil. Leave Client callable unchecked and Accessible from set to This application scope only. This custom diagnostic wraps OOB GlideAggregate; it does not replace attachment controls or quotas. 2. From an authorized Global server-side script, call: var summary = new AttachmentStorageUtil().summarize('incident', 'REPLACE_WITH_32_CHARACTER_SYS_ID'); Inspect summary.ok before using summary.count or summary.bytes. Replace the placeholder with a real record sys_id; it intentionally fails input validation as written. 3. The query matches the exact sys_attachment.table_name and table_sys_id pair. Use the internal table name stored on the attachment, not a label or a parent table such as task for an incident attachment. Special attachment table-name prefixes are not inferred. The utility does not check whether the parent table or record exists; zero attachments and a nonexistent record both return successful zero totals. 4. In sub-production, attach files of known byte lengths to a test record and compare count and bytes with sys_attachment metadata. Check a record with no attachments, an empty file, another record with attachments (excluded), an invalid sys_id (ok=false), and an incorrect but syntactically valid table name (zero totals). Remove a test attachment and verify the next call reflects the change. 5. bytes is the sum of size_bytes metadata, not physical database storage, compressed chunk storage, or a verified content length. No sys_attachment_doc rows or file contents are read. Concurrent attachment changes can affect the result; this is not a transactional upload-limit enforcement mechanism. 6. GlideAggregate here is an administrative query, not an ACL-filtered end-user endpoint. Keep this server-only and do not expose it through GlideAjax or a public API without separate parent-record and attachment authorization. Domain and execution context affect visibility. No cross-scope calls are needed for the documented Global usage; scoped reuse requires a separate access review. 7. If ok is false, disregard totals and check [SN-Tricks:AttachmentStorageUtil] in the system log. The Script Include performs no inserts, updates, or deletes. Capture the Script Include in your update set; test attachments are not part of that configuration. To roll back, remove dependent calls and deactivate the Script Include.

Adapt the table names, fields, and conditions to your instance. Test the behavior in a development environment before using it in production.