The Now Platform® Washington DC release is live. Watch now!

Help
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Download all Attachments from Attachments table

vijay39
Giga Expert

HI Folks,

I have a requirement like, i need to download all the attachments from sys_attachment table at once or 10k per time. Using REST i think i can do this. But can some one please help me in process how to download the attachments in bulk.

 

Regards,

Vijay

1 ACCEPTED SOLUTION

Hi Vijay,

You can use the same process as mentioned in this link. With slight modifications, you can get to download all attachments.

https://www.servicenowguru.com/scripting/download-attachments-zip-file/#comment-34336

Please note that the script might take time and if you want to limit to N number of records, you can do so in the below script. 

Few points to Note

1. The count variable is added to the file name to avoid duplicate file names. If there are duplicate file names, the zip process will break.

2. The script is modified to simply query sys_attachment and download them in the processor. It is not capturing any parameters from UI action as such. 

3. Create the UI action as a form button on any incident or any other table.

  var zipName = 'attachments.zip';
  var StringUtil = GlideStringUtil;
  var gr = new GlideRecord('sys_attachment');
  gr.query();
  if (gr.next()){
    g_response.setHeader('Pragma', 'public');
    g_response.addHeader('Cache-Control', 'max-age=0');
    g_response.setContentType('application/octet-stream');
    g_response.addHeader('Content-Disposition', 'attachment;filename=' + zipName);
    var out = new Packages.java.util.zip.ZipOutputStream(g_response.getOutputStream());
    var count=0;
    while (gr.next()){
        var sa = new GlideSysAttachment();
        var binData = sa.getBytes(gr); 
        //add counter so that the filename is NOT duplicate
        var file = gr.file_name+"-"+count; 
	gs.info("Entered into this loop"+file);
	addBytesToZip(out, zipName, file, binData);
        count ++;
    }
    // Complete the ZIP file
    out.close();
}

function addBytesToZip (out, dir, file, stream){
    // Add ZIP entry to output stream.
    out.putNextEntry(new Packages.java.util.zip.ZipEntry(file));
    out.write(stream, 0, stream.length);
    out.closeEntry();
}

I ran this in my dev instance and it worked fine. The script takes time to download all the attachments. To test the script, i suggest you break the loop above at 5 or 10 records.

Mark the comment as correct and also helpful once worked.

View solution in original post

19 REPLIES 19

sachin_namjoshi
Kilo Patron
Kilo Patron

Hi Sachin,

Thanks for your response, But in that i saw only attachments getting downloaded for a record. I want to download all the attachments from incident module. I see few docs saying we can accomplish that task using REST or SOAP, but i am not familiar with integrations as of now. So is there any other way to do this, or if i have to go only through Web Services, what is the exact process. Can you tell me the process if you are aware of this.

 

Regards,

Shankar

Hi Vijay,

You can use the same process as mentioned in this link. With slight modifications, you can get to download all attachments.

https://www.servicenowguru.com/scripting/download-attachments-zip-file/#comment-34336

Please note that the script might take time and if you want to limit to N number of records, you can do so in the below script. 

Few points to Note

1. The count variable is added to the file name to avoid duplicate file names. If there are duplicate file names, the zip process will break.

2. The script is modified to simply query sys_attachment and download them in the processor. It is not capturing any parameters from UI action as such. 

3. Create the UI action as a form button on any incident or any other table.

  var zipName = 'attachments.zip';
  var StringUtil = GlideStringUtil;
  var gr = new GlideRecord('sys_attachment');
  gr.query();
  if (gr.next()){
    g_response.setHeader('Pragma', 'public');
    g_response.addHeader('Cache-Control', 'max-age=0');
    g_response.setContentType('application/octet-stream');
    g_response.addHeader('Content-Disposition', 'attachment;filename=' + zipName);
    var out = new Packages.java.util.zip.ZipOutputStream(g_response.getOutputStream());
    var count=0;
    while (gr.next()){
        var sa = new GlideSysAttachment();
        var binData = sa.getBytes(gr); 
        //add counter so that the filename is NOT duplicate
        var file = gr.file_name+"-"+count; 
	gs.info("Entered into this loop"+file);
	addBytesToZip(out, zipName, file, binData);
        count ++;
    }
    // Complete the ZIP file
    out.close();
}

function addBytesToZip (out, dir, file, stream){
    // Add ZIP entry to output stream.
    out.putNextEntry(new Packages.java.util.zip.ZipEntry(file));
    out.write(stream, 0, stream.length);
    out.closeEntry();
}

I ran this in my dev instance and it worked fine. The script takes time to download all the attachments. To test the script, i suggest you break the loop above at 5 or 10 records.

Mark the comment as correct and also helpful once worked.

Hi Asifnoor,

Thank you for you reply. I have written the Processor like this,

var sysid = g_request.getParameter('sysparm_sys_id');
var table = g_request.getParameter('sysparm_table');

var theRecord = new GlideRecord(table);
theRecord.addQuery('sys_id', sysid);
theRecord.query();
theRecord.next();

//var zipName = 'attachments.zip';
var zipName = theRecord.number+'.zip';

var StringUtil = GlideStringUtil;

var gr = new GlideRecord('sys_attachment');
gr.addQuery('table_sys_id', theRecord.sys_id);
gr.addQuery('table_name', theRecord.getTableName());
gr.query();

if (gr.hasNext()){
g_response.setHeader('Pragma', 'public');
g_response.addHeader('Cache-Control', 'max-age=0');
g_response.setContentType('application/octet-stream');
g_response.addHeader('Content-Disposition', 'attachment;filename=' + zipName);
var out = new Packages.java.util.zip.ZipOutputStream(g_response.getOutputStream());
var count=0;
while (gr.next()){
var sa = new GlideSysAttachment();
var binData = sa.getBytes(gr);

var file = gr.file_name;
addBytesToZip(out, zipName, file, binData);
count ++;
}
// Complete the ZIP file
out.close();
}

function addBytesToZip (out, dir, file, stream){
// Add ZIP entry to output stream.
out.putNextEntry(new Packages.java.util.zip.ZipEntry(file));
out.write(stream, 0, stream.length);
out.closeEntry();
}

 

and in UI action:

on Incident table, and Form Button

Script:

action.setRedirectURL('exportAttachmentsToZip.do?sysparm_sys_id=' + current.sys_id + '&sysparm_table=' + current.getTableName());

 

So, it is downloading the attachment with its incident number as prefix. 

 

You are able to download all the attachments in your instance. So what changes to be done to my code if i have to get the desired result like you. I want to download all the attachments from sys_attachment table

Please suggest me

 

Regards,

Vijay