
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-20-2025 05:44 AM
Hi All,
There is widget created on on page to attach the attachments which is working fine. Requirement is, I need to add "Download All" button to that widget and write the code to download all the attached attachments.
I am new to portal. I am able to add the button but where I can write down the script and connect to "Download All" button ?
Regards,
Virendra
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-20-2025 07:38 AM
try this
HTML:
<div class="panel panel-{{options.color}} b">
<div class="panel-heading padder-b-none">
<h2 class="h4 sp-attachments-header panel-title pull-left">
${Attachments}
</h2>
<div hidden>
<sp-change-attachment-button></sp-change-attachment-button>
</div>
<i ng-if="data.checkTTSStatus" class="glyphicon glyphicon-paperclip pull-right" style="font-size:25px;margin-left: 266px;" id="btnOpenFileDialog" ng-click="openfileDialog()" data-toggle="modal" data-target="#myModal"></i>
<div class="clearfix"></div>
</div>
<div class="panel-body" ng-class="{'hidden-xs': !hasAttachments()}">
<div ng-if="data.canWrite && data.canAttach" ng-file-drop="dropFiles($files)" ng-multiple="true" class="sp-attachments">
<div ng-if="::data.canDragAndDrop" class="sp-no-attachments text-center text-italic text-muted" ng-show="!hasAttachments()">
<em class="sp-drop-area">${Drop files here}</em>
</div>
<div ng-if="::!data.canDragAndDrop" class="sp-no-attachments text-center text-muted" ng-show="!hasAttachments()">
<em>{{::data.noAttachmentsMsg}}</em>
</div>
<now-attachments-list template="sp_attachment" />
</div>
<div ng-if="!data.canWrite || !data.canAttach" class="sp-attachments">
<div class="sp-no-attachments text-center text-muted" ng-show="!hasAttachments()">
<em>{{::data.noAttachmentsMsg}}</em>
</div>
<now-attachments-list template="sp_attachment" />
</div>
</div>
<div>
<button type="button" class="btn btn-primary" id="downloadAllButton" ng-click="downloadAllAttachments()">Download All</button>
</div>
</div>
Client controller
function attachMate($scope, nowAttachmentHandler, spAttachmentUpload, $rootScope, spUtil, spModal, $log, spAriaUtil, $document) {
$scope.errorMessages = [];
$scope.attachmentHandler = new nowAttachmentHandler(setAttachments, appendError);
$scope.data.action = "";
$scope.confirmed = "";
$scope.canDeleteAttachment = $scope.data.checkTTSStatus;
var changeStatus = ['ready_for_review', 'more_information_required', 'review_complete', 'reschedule_requested'];
var fileArray = [];
var c = this;
$scope.openfileDialog = function() {
spUtil.setPreference("document_type", "");
$scope.opt.selectedOption = $scope.opt.availableOptions[0];
$scope.escalationOption.selectedOption = $scope.escalationOption.availableOptions[0];
};
if ($scope.data.isTTSPendingApproval == 'true') {
$("#attachmentButton").off().on("click", function() {
spUtil.setPreference("document_type", $scope.escalationOption.selectedOption.value);
$(".change-attachment-add").trigger("click");
});
} else {
$("#attachmentButton").off().on("click", function() {
spUtil.setPreference("document_type", $scope.opt.selectedOption.value);
$(".change-attachment-add").trigger("click");
});
}
$rootScope.$on("spModelTabbed.track_tab", function(e, d) {
spUtil.setPreference("document_type", "");
});
$scope.escalationOption = {
availableOptions: $scope.data.escalation_attachcontent
};
$scope.opt = {
availableOptions: $scope.data.attachcontent
};
spUtil.recordWatch($scope, "sys_attachment", "table_sys_id=" + $scope.data.sys_id, function(response, data) {
$scope.attachmentHandler.getAttachmentList();
if (response.data) {
var options = {};
options.operation = response.data.operation;
options.filename = response.data.display_value;
options.sys_id = $scope.data.sys_id;
options.table = $scope.data.table;
options.state = (response.data.record && response.data.record.state) ? response.data.record.state.value : "";
if (options.operation === "update" && options.state === "not_available")
$rootScope.$broadcast("attachment.updated", options);
}
if (options.operation == 'insert' && changeStatus.indexOf(c.data.change_state) > -1 && $scope.data.classicView == 'tabbed_form') {
spUtil.addErrorMessage('Please add work notes in Communication tab that a new attachment has been added for the Change desk to review');
}
});
$scope.$evalAsync(function() {
$scope.attachmentHandler.setParams($scope.data.table, $scope.data.sys_id, 1024 * 1024 * $scope.data.maxAttachmentSize);
$scope.attachmentHandler.getAttachmentList();
});
$scope.hasAttachments = function() {
return $scope.attachments && $scope.attachments.length != 0;
};
$scope.canWrite = function() {
return $scope.data.canWrite;
};
$scope.dropFiles = function(files) {
if (!$scope.data.canDragAndDrop) {
spUtil.addInfoMessage(data.noDragDropMsg);
return;
}
spAttachmentUpload.uploadAttachments($scope.attachmentHandler, files);
};
$scope.confirmDeleteAttachment = function(attachment) {
var appendTo = $scope.data.appendToId ? $document.find('#' + $scope.data.appendToId) : null;
spModal.confirm("${Delete Attachment?}", appendTo).then(function() {
$scope.attachmentHandler.deleteAttachment(attachment);
$scope.setFocusToAttachmentButton();
});
};
$scope.$on('dialog.upload_too_large.show', function(e) {
$log.error($scope.data.largeAttachmentMsg);
spUtil.addErrorMessage($scope.data.largeAttachmentMsg);
});
$scope.$on('added_attachment', function(evt) {
$scope.data.action = "added";
spUtil.update($scope);
});
$scope.$on('sn.attachment.scanned', function(evt) {
$scope.attachmentHandler.getAttachmentList("list");
});
$scope.$on('sp.record.can_write', function(evt, answer) {
$scope.data.canWrite = answer;
});
function appendError(error) {
$scope.errorMessages.push(error);
spUtil.addErrorMessage(error.msg + error.fileName);
}
function setAttachments(attachments, action) {
if ($scope.submitting == true)
return;
$scope.attachments = attachments;
if (!$scope.canDeleteAttachment) {
attachments.forEach(function(attachment) {
attachment.canDelete = false;
attachment.canWrite = false;
});
}
if (!action)
return;
if (action === "added") {
spAriaUtil.sendLiveMessage($scope.data.attachmentSuccessMsg);
}
$scope.data.action = action;
spUtil.update($scope);
}
$scope.downloadAllAttachments = function() {
var attachments = $scope.attachments;
if (attachments && attachments.length > 0) {
attachments.forEach(function(attachment) {
var url = '/sys_attachment.do?sys_id=' + attachment.sys_id;
var link = document.createElement('a');
link.href = url;
link.download = attachment.file_name;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
} else {
spUtil.addErrorMessage("No attachments available to download.");
}
};
}
If my response helped please mark it correct and close the thread so that it benefits future readers.
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-20-2025 05:47 AM
share the complete widget script and download all means download all files from that current record?
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-20-2025 06:28 AM - edited 02-20-2025 06:30 AM
Hi @Ankur Bawiskar
Yes , download all files from that current record.
Here is the code,
HTML code
<!--<div hidden >fa fa-paperclip pull-right
<div>
<sp-change-attachment-button></sp-change-attachment-button>
</div>
<div class="clearfix"></div>
</div> -->
<div class="panel panel-{{options.color}} b">
<div class="panel-heading padder-b-none">
<h2 class="h4 sp-attachments-header panel-title pull-left">
${Attachments}
</h2>
<div hidden>
<sp-change-attachment-button></sp-change-attachment-button>
</div>
<i ng-if = "data.checkTTSStatus" class="glyphicon glyphicon-paperclip pull-right" style="font-size:25px;margin-left: 266px;" id="btnOpenFileDialog" ng-click ="openfileDialog()" data-toggle="modal" data-target="#myModal"> </i>
<div class="clearfix"></div>
</div>
<!-- small device - hide body unless there are attachments -->
<div class="panel-body" ng-class="{'hidden-xs': !hasAttachments()}">
<div ng-if="data.canWrite && data.canAttach" ng-file-drop="dropFiles($files)" ng-multiple="true" class="sp-attachments">
<div ng-if="::data.canDragAndDrop" class="sp-no-attachments text-center text-italic text-muted" ng-show="!hasAttachments()">
<em class="sp-drop-area">${Drop files here}</em>
</div>
<div ng-if="::!data.canDragAndDrop" class="sp-no-attachments text-center text-muted" ng-show="!hasAttachments()">
<em>{{::data.noAttachmentsMsg}}</em>
</div>
<now-attachments-list template="sp_attachment" />
</div>
<div ng-if="!data.canWrite || !data.canAttach" class="sp-attachments">
<div class="sp-no-attachments text-center text-muted" ng-show="!hasAttachments()">
<em>{{::data.noAttachmentsMsg}}</em>
</div>
<now-attachments-list template="sp_attachment" />
</div>
</div>
<!-- Modal content-->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title text-center">Document Attachment</h4>
</div>
<div class="modal-body" ng-if="data.isTTSPendingApproval == 'false'">
<h4 class="modal-title doc-heading">Please Select Document Type</h4>
<label for="mySelect" >Document Type : </label>
<select class="selectpicker" name="mySelect" id="mySelect"
ng-options="option.name for option in opt.availableOptions track by option.id"
ng-model="opt.selectedOption"></select>
</div>
<div class="modal-body" ng-if="data.isTTSPendingApproval == 'true'">
<h4 class="modal-title doc-heading">Please Select Document Type</h4>
<label for="mySelect" >Document Type : </label>
<select class="selectpicker" name="mySelect" id="mySelect"
ng-options="option.name for option in escalationOption.availableOptions track by option.id"
ng-model="escalationOption.selectedOption"></select>
</div>
<!--ng-if="data.isTTSPendingApproval == 'false'"-->
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="attachmentButton" data-dismiss="modal">Attachment</button>
</div>
</div>
</div>
</div>
<div> <button type="button" class="btn btn-primary" id="downloadAllButton" data-dismiss="modal">Download All</button> </div>
====================================================================
Server Script -
Client Controller -
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-20-2025 07:38 AM
try this
HTML:
<div class="panel panel-{{options.color}} b">
<div class="panel-heading padder-b-none">
<h2 class="h4 sp-attachments-header panel-title pull-left">
${Attachments}
</h2>
<div hidden>
<sp-change-attachment-button></sp-change-attachment-button>
</div>
<i ng-if="data.checkTTSStatus" class="glyphicon glyphicon-paperclip pull-right" style="font-size:25px;margin-left: 266px;" id="btnOpenFileDialog" ng-click="openfileDialog()" data-toggle="modal" data-target="#myModal"></i>
<div class="clearfix"></div>
</div>
<div class="panel-body" ng-class="{'hidden-xs': !hasAttachments()}">
<div ng-if="data.canWrite && data.canAttach" ng-file-drop="dropFiles($files)" ng-multiple="true" class="sp-attachments">
<div ng-if="::data.canDragAndDrop" class="sp-no-attachments text-center text-italic text-muted" ng-show="!hasAttachments()">
<em class="sp-drop-area">${Drop files here}</em>
</div>
<div ng-if="::!data.canDragAndDrop" class="sp-no-attachments text-center text-muted" ng-show="!hasAttachments()">
<em>{{::data.noAttachmentsMsg}}</em>
</div>
<now-attachments-list template="sp_attachment" />
</div>
<div ng-if="!data.canWrite || !data.canAttach" class="sp-attachments">
<div class="sp-no-attachments text-center text-muted" ng-show="!hasAttachments()">
<em>{{::data.noAttachmentsMsg}}</em>
</div>
<now-attachments-list template="sp_attachment" />
</div>
</div>
<div>
<button type="button" class="btn btn-primary" id="downloadAllButton" ng-click="downloadAllAttachments()">Download All</button>
</div>
</div>
Client controller
function attachMate($scope, nowAttachmentHandler, spAttachmentUpload, $rootScope, spUtil, spModal, $log, spAriaUtil, $document) {
$scope.errorMessages = [];
$scope.attachmentHandler = new nowAttachmentHandler(setAttachments, appendError);
$scope.data.action = "";
$scope.confirmed = "";
$scope.canDeleteAttachment = $scope.data.checkTTSStatus;
var changeStatus = ['ready_for_review', 'more_information_required', 'review_complete', 'reschedule_requested'];
var fileArray = [];
var c = this;
$scope.openfileDialog = function() {
spUtil.setPreference("document_type", "");
$scope.opt.selectedOption = $scope.opt.availableOptions[0];
$scope.escalationOption.selectedOption = $scope.escalationOption.availableOptions[0];
};
if ($scope.data.isTTSPendingApproval == 'true') {
$("#attachmentButton").off().on("click", function() {
spUtil.setPreference("document_type", $scope.escalationOption.selectedOption.value);
$(".change-attachment-add").trigger("click");
});
} else {
$("#attachmentButton").off().on("click", function() {
spUtil.setPreference("document_type", $scope.opt.selectedOption.value);
$(".change-attachment-add").trigger("click");
});
}
$rootScope.$on("spModelTabbed.track_tab", function(e, d) {
spUtil.setPreference("document_type", "");
});
$scope.escalationOption = {
availableOptions: $scope.data.escalation_attachcontent
};
$scope.opt = {
availableOptions: $scope.data.attachcontent
};
spUtil.recordWatch($scope, "sys_attachment", "table_sys_id=" + $scope.data.sys_id, function(response, data) {
$scope.attachmentHandler.getAttachmentList();
if (response.data) {
var options = {};
options.operation = response.data.operation;
options.filename = response.data.display_value;
options.sys_id = $scope.data.sys_id;
options.table = $scope.data.table;
options.state = (response.data.record && response.data.record.state) ? response.data.record.state.value : "";
if (options.operation === "update" && options.state === "not_available")
$rootScope.$broadcast("attachment.updated", options);
}
if (options.operation == 'insert' && changeStatus.indexOf(c.data.change_state) > -1 && $scope.data.classicView == 'tabbed_form') {
spUtil.addErrorMessage('Please add work notes in Communication tab that a new attachment has been added for the Change desk to review');
}
});
$scope.$evalAsync(function() {
$scope.attachmentHandler.setParams($scope.data.table, $scope.data.sys_id, 1024 * 1024 * $scope.data.maxAttachmentSize);
$scope.attachmentHandler.getAttachmentList();
});
$scope.hasAttachments = function() {
return $scope.attachments && $scope.attachments.length != 0;
};
$scope.canWrite = function() {
return $scope.data.canWrite;
};
$scope.dropFiles = function(files) {
if (!$scope.data.canDragAndDrop) {
spUtil.addInfoMessage(data.noDragDropMsg);
return;
}
spAttachmentUpload.uploadAttachments($scope.attachmentHandler, files);
};
$scope.confirmDeleteAttachment = function(attachment) {
var appendTo = $scope.data.appendToId ? $document.find('#' + $scope.data.appendToId) : null;
spModal.confirm("${Delete Attachment?}", appendTo).then(function() {
$scope.attachmentHandler.deleteAttachment(attachment);
$scope.setFocusToAttachmentButton();
});
};
$scope.$on('dialog.upload_too_large.show', function(e) {
$log.error($scope.data.largeAttachmentMsg);
spUtil.addErrorMessage($scope.data.largeAttachmentMsg);
});
$scope.$on('added_attachment', function(evt) {
$scope.data.action = "added";
spUtil.update($scope);
});
$scope.$on('sn.attachment.scanned', function(evt) {
$scope.attachmentHandler.getAttachmentList("list");
});
$scope.$on('sp.record.can_write', function(evt, answer) {
$scope.data.canWrite = answer;
});
function appendError(error) {
$scope.errorMessages.push(error);
spUtil.addErrorMessage(error.msg + error.fileName);
}
function setAttachments(attachments, action) {
if ($scope.submitting == true)
return;
$scope.attachments = attachments;
if (!$scope.canDeleteAttachment) {
attachments.forEach(function(attachment) {
attachment.canDelete = false;
attachment.canWrite = false;
});
}
if (!action)
return;
if (action === "added") {
spAriaUtil.sendLiveMessage($scope.data.attachmentSuccessMsg);
}
$scope.data.action = action;
spUtil.update($scope);
}
$scope.downloadAllAttachments = function() {
var attachments = $scope.attachments;
if (attachments && attachments.length > 0) {
attachments.forEach(function(attachment) {
var url = '/sys_attachment.do?sys_id=' + attachment.sys_id;
var link = document.createElement('a');
link.href = url;
link.download = attachment.file_name;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
} else {
spUtil.addErrorMessage("No attachments available to download.");
}
};
}
If my response helped please mark it correct and close the thread so that it benefits future readers.
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-21-2025 07:01 AM
Hi @Ankur Bawiskar Thank you.
Code is working, but its NOT downloading all the attached file. I have 3 attachments but only one attachment is getting downloaded.
Can you please check once ?
Regards,
Virendra