- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2023 09:33 PM
I customized a widget to attach files. But when the attachment file is downloaded, the content is empty. What am I missing? Please someone help me
The Code as below:
Body HTML template :
<div>
<br/><br/> File: <input type="file" id="fileToUpload" multiple onchange="angular.element(this).scope().setFiles(this)"/>
<br/> <div ng-show="files.length">
<div ng-repeat="file in files.slice(0)">
<span>{{file.webkitRelativePath || file.name}}</span>
(<span ng-switch="file.size > 1024*1024">
<span ng-switch-when="true">{{file.size / 1024 / 1024 | number:2}} MB</span>
<span ng-switch-default>{{file.size / 1024 | number:2}} kB</span>
</span>)
<span class="glyphicon glyphicon-remove-circle" id="removeicon" ng-click="removeFiles(file)"></span>
</div>
<input type="button" ng-click="c.attach()" value="Upload" />
</div>
</div>
Client Controller :
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2023 11:37 PM
Hi @Dinh Nguyen ,
If REST API access is blocked and you need to attach files to the login page of the Service Portal, you might consider using ServiceNow's Scripted REST APIs. Scripted REST APIs allow you to create custom API endpoints within ServiceNow using server-side scripting.
Here's a high-level overview of how you could use Scripted REST APIs to achieve your goal:
1. **Create a Scripted REST API Endpoint:**
- Navigate to `System Web Services` > `Scripted REST APIs` in the application navigator.
- Create a new API endpoint. Define the endpoint URL, HTTP methods, authentication requirements, and other settings.
2. **Write a Script to Handle File Upload:**
- In the Scripted REST API endpoint, write a script that handles file uploads. Use GlideSysAttachment or GlideRecord APIs to attach the files to the Service Portal's login page.
- Ensure your script handles authentication and authorization properly.
3. **Invoke the Scripted REST API from Service Portal:**
- Within your Service Portal widget or client script, make a client-side AJAX request to the Scripted REST API endpoint you created.
- Use the ServiceNow `XMLHttpRequest` or `$http` AngularJS service to send the request to the Scripted REST API endpoint.
- Pass the file data in the request body. You might need to encode the file data appropriately, such as using `FormData` for file uploads.
Here's a simplified example of how you can make an AJAX request from a Service Portal widget using AngularJS `$http` service:
api.controller = function($scope, $http) {
var c = this;
$scope.files = [];
// Function to handle file input change
$scope.setFiles = function(element) {
$scope.$apply(function() {
$scope.files = element.files;
});
};
// Function to upload files using Scripted REST API
c.attach = function() {
var fd = new FormData();
angular.forEach($scope.files, function(file) {
fd.append('file', file);
});
// Make a POST request to the Scripted REST API endpoint
$http({
method: 'POST',
url: '/api/custom/file-upload-endpoint', // Replace with your Scripted REST API endpoint URL
data: fd,
headers: { 'Content-Type': undefined } // Let the browser set the content type
}).then(function(response) {
// Handle the response if needed
console.log('File uploaded successfully:', response);
}, function(error) {
console.error('Failed to upload file:', error);
});
};
};
Please ensure that you have the appropriate permissions set for the Scripted REST API and that the script in the Scripted REST API endpoint handles the file upload operation securely. Also, remember to test thoroughly in a development or non-production environment to ensure everything works as expected.
Mark as helpful & accepted if it helps you achieve your requirement.
Thanks,
Danish
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2023 09:55 PM
Hi @Dinh Nguyen ,
The issue you are facing might be related to the way you are handling file uploads and FormData in your client-side controller. Let me provide you with some modifications to your code to ensure proper handling of file uploads and attachments in ServiceNow.
Changes in Client Controller:
api.controller = function($scope) {
var c = this;
$scope.files = [];
// Function to handle file input change
$scope.setFiles = function(element) {
$scope.$apply(function() {
$scope.files = element.files;
});
};
// Function to upload files
c.attach = function() {
var fd = new FormData();
angular.forEach($scope.files, function(file) {
fd.append('file', file);
});
// Sending the files using AJAX
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/now/attachment/upload'); // Replace with the appropriate attachment API endpoint URL
xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('X-UserToken', g_ck); // Use user token for authentication, ensure g_ck is defined in your scope
xhr.onload = function() {
if (xhr.status === 200) {
var response = JSON.parse(xhr.responseText);
// Handle the response if needed
} else {
console.error('Failed to upload files');
}
};
xhr.send(fd);
};
};
Changes in Server Script:
(function() {
if (input && input.action === 'attachFile') {
attachFile();
}
function attachFile() {
var attachmentSysId;
var tableSysId = "5ed1d41047bd311093127748c26d43c9"; // Replace with the target record's Sys ID
var tableName = "u_public_table"; // Replace with the target table name
var attachment = new GlideSysAttachment();
attachment.write(tableSysId, tableName, input.fileInfoAttach, input.fileType);
attachmentSysId = attachment.sys_id;
// If you need to perform additional operations or return the attachment Sys ID, you can do so here.
// Return the attachmentSysId if needed
// action.setReturn(attachmentSysI
d);
}
})();
Notes:
Client-Side Changes:
I modified the way files are appended to the FormData object to ensure correct handling during the upload process.
I used an XMLHttpRequest to handle the file upload asynchronously. Adjust the API endpoint URL according to your ServiceNow instance configuration.
Ensure proper authentication and user token (g_ck) handling for the API request.
Server-Side Changes:
I used GlideSysAttachment to write the attachment, assuming that you are uploading files to a specific record in a specific table.
Adjust tableSysId and tableName variables to match your use case.
Remember to customize the server-side logic further based on your specific requirements.
Mark my answer helpful & accepted if it helps you resolve your query.
Thanks,
Danish
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2023 10:26 PM
Hi @Danish Bhairag2 ,
Thank you for reply me !
But the problem here is that my requirement is to attach the file to the login page of the Service Portal! That's why I handled it like that! I tried using REST Api but it is blocked from access
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
10-07-2023 11:37 PM
Hi @Dinh Nguyen ,
If REST API access is blocked and you need to attach files to the login page of the Service Portal, you might consider using ServiceNow's Scripted REST APIs. Scripted REST APIs allow you to create custom API endpoints within ServiceNow using server-side scripting.
Here's a high-level overview of how you could use Scripted REST APIs to achieve your goal:
1. **Create a Scripted REST API Endpoint:**
- Navigate to `System Web Services` > `Scripted REST APIs` in the application navigator.
- Create a new API endpoint. Define the endpoint URL, HTTP methods, authentication requirements, and other settings.
2. **Write a Script to Handle File Upload:**
- In the Scripted REST API endpoint, write a script that handles file uploads. Use GlideSysAttachment or GlideRecord APIs to attach the files to the Service Portal's login page.
- Ensure your script handles authentication and authorization properly.
3. **Invoke the Scripted REST API from Service Portal:**
- Within your Service Portal widget or client script, make a client-side AJAX request to the Scripted REST API endpoint you created.
- Use the ServiceNow `XMLHttpRequest` or `$http` AngularJS service to send the request to the Scripted REST API endpoint.
- Pass the file data in the request body. You might need to encode the file data appropriately, such as using `FormData` for file uploads.
Here's a simplified example of how you can make an AJAX request from a Service Portal widget using AngularJS `$http` service:
api.controller = function($scope, $http) {
var c = this;
$scope.files = [];
// Function to handle file input change
$scope.setFiles = function(element) {
$scope.$apply(function() {
$scope.files = element.files;
});
};
// Function to upload files using Scripted REST API
c.attach = function() {
var fd = new FormData();
angular.forEach($scope.files, function(file) {
fd.append('file', file);
});
// Make a POST request to the Scripted REST API endpoint
$http({
method: 'POST',
url: '/api/custom/file-upload-endpoint', // Replace with your Scripted REST API endpoint URL
data: fd,
headers: { 'Content-Type': undefined } // Let the browser set the content type
}).then(function(response) {
// Handle the response if needed
console.log('File uploaded successfully:', response);
}, function(error) {
console.error('Failed to upload file:', error);
});
};
};
Please ensure that you have the appropriate permissions set for the Scripted REST API and that the script in the Scripted REST API endpoint handles the file upload operation securely. Also, remember to test thoroughly in a development or non-production environment to ensure everything works as expected.
Mark as helpful & accepted if it helps you achieve your requirement.
Thanks,
Danish