Fetching All Attachments From A List Using SharePoint Framework WebPart

Here, we are going to learn how to fetch all the attachments from a SharePoint List using SharePoint Framework with PnP JavaScript library.

Often, in forums and SharePoint events, I receive a query on how to get all the attachments from all items in a SharePoint List. We can achieve this in several different ways as mentioned below.

  • Accessing the attachments folder from the SharePoint List using SharePoint Designer
  • Mapping the attachments folder to File Share.
  • Accessing the attachment folder of the list based on the path using a program
  • Get the attachments of each list item in a list using a program

Here, we are going to follow the last method for accessing the attachments in a list using PnP JavaScript library and render that in SharePoint Framework webpart.

First of all, create a SharePoint Framework webpart project using the Yeoman generator with the following command.

  1. PS> yo @microsoft/sharepoint 

Generate the project with No JavaScript option, because I am going to show the example without any JavaScript framework so that, you can use the snippet of any JavaScript framework on creating the webpart.

After the creation of the project, add the PnP JS library dependencies by running the following npm commmand.

  1. PS> npm install –save @pnp/common @pnp/sp @pnp/logging @pnp/odata 
To access the item and attachment objects using PnP library, add the following import statements to the webpart's TypeScript file.
  1. import { sp, Item } from "@pnp/sp"
If we want to download or upload the attachment files from the webpart, we have to include the following import statement below the sp import statement.
  1. import { AttachmentFile, AttachmentFiles, AttachmentFileInfo } from '@pnp/sp/src/attachmentfiles'
To show the attachments from all list items in a webpart, add the below methods under the _WebPart class within the _webpart.ts file.
  1. //Retrieve all the attachments from all items in a SharePoint List  
  2.   private getSPData(): void {  
  3.     let attachmentfiles: string = "";  
  4.    
  5.     sp.web.lists.getByTitle("My List").items  
  6.     .select("Id,Title,Attachments,AttachmentFiles")  
  7.     .expand("AttachmentFiles")  
  8.     .filter('Attachments eq 1')  
  9.     .get().then((response: Item[]) => {  
  10.        
  11.       response.forEach((listItem: any) => {  
  12.         listItem.AttachmentFiles.forEach((afile: any) => {  
  13.           attachmentfiles += `<li>(${listItem.Id}) ${listItem.Title} - ${afile.FileName}</li>`;  
  14.         });  
  15.    
  16.       });      
  17.       attachmentfiles = `<ul>${attachmentfiles}</ul>`;;  
  18.       this.renderData(attachmentfiles);  
  19.     });  
  20.   }  
  21. private renderData(strResponse: string): void {  
  22.   const htmlElement = this.domElement.querySelector("#pnpinfo");  
  23.   htmlElement.innerHTML = strResponse;  

The getSPData() method gets the attachment files from all items from the list “My List“. Add the “Attachments eq 1” to the filter to retrieve the items which contain attachments. Use the expand method to get the attachment files of the list items in a single request.

In response, we are generating the HTML as a list of attachment files with the associated Item Id and Title. The renderData() method adds the generated HTML to the webpart.

Replace the render() method with the below code snippet. This is used to call the getSPData() and update the retrieved values within the element pnpinfo.

  1. public render(): void {  
  2.   this.domElement.innerHTML = `  
  3.     <div class="${ styles.pnPDemos}">  
  4.       <div class="${ styles.container}">  
  5.         <div class="${ styles.row}">  
  6.           <div class="${ styles.column}">  
  7.             <div id="pnpinfo"></div>  
  8.           </div>  
  9.         </div>  
  10.       </div>  
  11.     </div>`;  
  12.   this.getSPData();  

After running the webpart in the SharePoint page, it will display the Item id, title, and attachments. It will be nice to have a download link in the attachment file.
  1. attachmentfiles += `<li>(${listItem.Id}) ${listItem.Title} - ${afile.FileName}</li>`; 
 Replace the above line with the following code snippet. Then, the webpart renders the download link of each attachment file.
  1. let downloadUrl = this.context.pageContext.web.absoluteUrl + "/_layouts/download.aspx?sourceurl=" + afile.ServerRelativeUrl;  
  2. attachmentfiles += `<li>(${listItem.Id}) ${listItem.Title} - <a href='${downloadUrl}'>${afile.FileName}</a></li>`; 
 And the output looks like below.