Attachments in SharePoint lists are widely used to associate documents, images, or other files with list items. In modern SharePoint development, managing these attachments programmatically is essential for custom applications, workflows, and integrations.
With the PnPjs library inside your SPFx solution, you can easily upload, read, download, and delete attachments with clean, readable code. This article explores best practices and real-world examples for handling SharePoint list item attachments using PnPjs.
Prerequisites
Before working with attachments, ensure the following:
- A SharePoint Framework (SPFx) project is set up.
- Install the PnPjs library:
npm install @pnp/sp @pnp/graph --save
- Import required modules in your component or service:
import { spfi, SPFx } from "@pnp/sp";
import "@pnp/sp/webs";
import "@pnp/sp/lists";
import "@pnp/sp/items";
import "@pnp/sp/attachments";
Initialize the sp
object in your component’s constructor or onInit
method:
const sp = spfi().using(SPFx(this.props.context));
Uploading Attachments
To attach a file to a SharePoint list item:
const uploadAttachment = async (listName: string, itemId: number, file: File) => {
try {
await sp.web.lists.getByTitle(listName)
.items.getById(itemId)
.attachmentFiles.add(file.name, await file.arrayBuffer());
console.log(`Attachment ${file.name} uploaded successfully.`);
} catch (error) {
console.error("Error uploading attachment:", error);
}
};
✅ The method .attachmentFiles.add()
accepts a file name and content as an ArrayBuffer
.
Retrieving Attachments
To get all attachments for a specific item:
const getAttachments = async (listName: string, itemId: number) => {
try {
const attachments = await sp.web.lists.getByTitle(listName)
.items.getById(itemId)
.attachmentFiles();
console.log("Attachments:", attachments);
return attachments;
} catch (error) {
console.error("Error retrieving attachments:", error);
}
};
The response includes an array of attachments with properties like FileName
and ServerRelativeUrl
.
Downloading Attachments
To download an attachment, fetch its content using fetchBlob()
:
const downloadAttachment = async (listName: string, itemId: number, fileName: string) => {
try {
const file = await sp.web.lists.getByTitle(listName)
.items.getById(itemId)
.attachmentFiles.getByName(fileName)
.getBlob();
// Trigger download in browser
const url = window.URL.createObjectURL(file);
const a = document.createElement("a");
a.href = url;
a.download = fileName;
a.click();
console.log(`Attachment ${fileName} downloaded.`);
} catch (error) {
console.error("Error downloading attachment:", error);
}
};
Deleting Attachments
To remove a specific attachment:
const deleteAttachment = async (listName: string, itemId: number, fileName: string) => {
try {
await sp.web.lists.getByTitle(listName)
.items.getById(itemId)
.attachmentFiles.getByName(fileName)
.delete();
console.log(`Attachment ${fileName} deleted.`);
} catch (error) {
console.error("Error deleting attachment:", error);
}
};
Best Practices
- Validate file types & size before uploading to maintain governance.
- Use SPFx Property Pane configuration to make the list name dynamic.
- Implement progress indicators for large uploads.
- Store metadata (e.g., file type, uploaded by, upload date) in columns for improved searchability.
- Avoid using attachments for critical document storage — consider document libraries instead.
Conclusion
Managing attachments with PnPjs in SPFx is straightforward and efficient. With simple APIs for add, get, download, and delete, developers can build user-friendly interfaces for handling list item attachments in SharePoint Online.
By combining these APIs with modern UI frameworks like Fluent UI or Mantine, you can deliver seamless user experiences for attachment management in enterprise solutions.