- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Good Morning Guys!
At the moment, i make a Widget and this is on a public site (no authication).
In this Widget i want to make downloading files from sys_attachment.
first of all, i used the url /sys_attchment?sys_id=<SYSID>, but if i am not logged in, i dont can download the file.
After this, i try to make a restapi.. but this doesnt have permission to the sys_attachments...
After this, i try with a base64.. but it doesnt work..
Here is my Code:
Server Script:
Client Controller:
Thanks and regards
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hey there,
I've now found a solution and would like to share it with you.
In case you encounter the same problem.
See for yourself:
Server script:
(function() {
data.attachments = [];
var gr = new GlideRecord('sys_attachment');
// add your query
gr.query();
var sa = new GlideSysAttachment();
while (gr.next()) {
try {
var bytes = sa.getBytes(gr);
if (bytes && bytes.length > 0) {
var base64 = GlideStringUtil.base64Encode(bytes);
data.attachments.push({
name: gr.getValue('file_name'),
sys_id: gr.getValue('sys_id'),
content_type: gr.getValue('content_type'),
size: gr.getValue('size_bytes'),
base64: base64
});
}
} catch(ex) {
gs.error('Error in File ' + ex.message);
}
}
})();
And this is my Client controller:
api.controller = function($scope, spUtil) {
var c = this;
c.attachments = c.data.attachments || [];
c.download = function(att) {
try {
var byteChars = atob(att.base64);
var byteNumbers = new Array(byteChars.length);
for (var i = 0; i < byteChars.length; i++) {
byteNumbers[i] = byteChars.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: att.content_type });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = att.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch(e) {
alert('Error by downloading: ' + e.message);
}
};
}But thanks, for the help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
@CyrillW if everything else is down, why not to use your ServiceNow credentials like always?
I don't know how to help you because I don't really understand the requirement. sorry...
No AI was used in the writing of this post. Pure #GlideFather only
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
@GlideFather
The only thing I need is a way to display or download files using a widget if they are stored in sys_attachment – or any other method.
Important: It must work without login, just like accessing google.com.
Nothing else really matters. These are my requirements – the why or how is completely irrelevant.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago - last edited 3 weeks ago
Hi @CyrillW
Just for you to understand, conceptionally, public role and sys_attachment is a big no no in ServiceNow, so you'll be struggling to find an out of the box way to interact with the sys_attachment table directly without opening yourself up to an attack.
There's the sys_property glide.attachment.role where you can add the 'public' role. That won't work on all portals tho.
If this doesn't work for you, what I would suggest is looking to leverage the $scope object to store the attachments before submit. On Submit, you can create them in sys_attachment and map them to the target record.
Lastly, I would recommend you look to secure the form and the submit to minimise risk of unwanted requests being created. I would recommend leveraging Authentication.. any... or maybe a check on get/set clientData based on a server side logic(API Reference).
Good luck!
Tomas
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hey @Tomas Lozano
First of all, thank you for your explanation.
I am aware that this would be a very serious security vulnerability. However, I don't want to upload anything, I want to download something.
That's why this solution won't work.
Nevertheless, thank you very much for your help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hey there,
I've now found a solution and would like to share it with you.
In case you encounter the same problem.
See for yourself:
Server script:
(function() {
data.attachments = [];
var gr = new GlideRecord('sys_attachment');
// add your query
gr.query();
var sa = new GlideSysAttachment();
while (gr.next()) {
try {
var bytes = sa.getBytes(gr);
if (bytes && bytes.length > 0) {
var base64 = GlideStringUtil.base64Encode(bytes);
data.attachments.push({
name: gr.getValue('file_name'),
sys_id: gr.getValue('sys_id'),
content_type: gr.getValue('content_type'),
size: gr.getValue('size_bytes'),
base64: base64
});
}
} catch(ex) {
gs.error('Error in File ' + ex.message);
}
}
})();
And this is my Client controller:
api.controller = function($scope, spUtil) {
var c = this;
c.attachments = c.data.attachments || [];
c.download = function(att) {
try {
var byteChars = atob(att.base64);
var byteNumbers = new Array(byteChars.length);
for (var i = 0; i < byteChars.length; i++) {
byteNumbers[i] = byteChars.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], { type: att.content_type });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = att.name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch(e) {
alert('Error by downloading: ' + e.message);
}
};
}But thanks, for the help.