Preserving Deleted Files in SharePoint Online Using Power Automate

March 16, 2023
16 min read

The SharePoint Recycle Bin lets users recover files they may have inadvertently deleted. SharePoint Online allows users 93 days during which they can go to the recycle bin to recover the files and have them placed back in their original location. However, at times, users may need a longer grace period. While SharePoint on-premises provides such flexibility, the limit in SharePoint Online is fixed. In this article, I discuss how Power Automate can be leveraged to deal with such limitations.

Custom Recycle Bin

One option is to create a separate document library that can act as the Recycle Bin. This custom recycle bin needs to have a custom column added to it called Original Location (single line of text), which will contain the original location of the file that was deleted.

Screenshot of a SharePoint Online document library with a custom single line of text column named Original Location.
Figure 1: A custom document library is created with a single line of text custom column (named Original Location) to store the original file location.   Used with permission from Microsoft.

Rather than relying on the built-in Recycle Bin, the custom recycle bin can store files indefinitely.

The Workflow

When a user deletes a file from within a site, Power Automate can automatically detect the deletion and perform the following tasks:

  1. Temporarily restore the file to its original location.
  2. Move the file to a custom recycle bin document library.
  3. Add the Original Location file path to the file in the custom recycle bin (just as in the built-in Recycle Bin).
Screenshot of a Power Automate workflow for detecting a file that is being deleted on a SharePoint Online site and moving it into a custom Recycle Bin. The workflow triggers when a file is deleted, restores the file to its original location, moves it to a custom Recycle Bin, and finally adds the value of the Original Location to the file in the custom Recycle Bin.
Figure 2: Power Automate Workflow overview for detecting a file that is being deleted on a SharePoint Online site and moving it into a custom recycle bin.   Used with permission from Microsoft.

The Trigger

The SharePoint Online connector for Power Automate has a trigger to detect file deletion that is associated with a specific document library. As this would require having a workflow created for each document library, I elected to build this solution to work on an entire site. To do so, I use a timer that will check for new files in the Recycle Bin every 15 minutes.

Screenshot of a Power Automate Recurrence trigger set to 15-minute interval.
Figure 3: Power Automate Recurrence trigger set to 15 minutes.   Used with permission from Microsoft.

 

Retrieving Files Recently Moved to the Recycle Bin

After the trigger fires, Power Automate uses the Send an HTTP Request SharePoint action, which I renamed to Retrieve files from recycle bin in my workflow, to access files that are in the Recycle Bin. To avoid duplicating files that are already in the custom recycle bin, Power Automate limits the retrieval to files that were added in the last 15 minutes.

Screenshot of a Power Automate timer action to subtract 15 minutes from the current time and then using the resulting time to retrieve only files from the Recycle Bin that were added in the last 15 minutes
Figure 4: Using the Send an HTTP Request together with a time object to retrieve only recent files in Recycle Bin.   Used with permission from Microsoft.

The files retrieved are then passed to a Parse JSON action so that individual files can be retrieved. There are three specific pieces of information needed:

  • File ID
  • DirName
  • LeafName

Use the following schema to ensure that all relevant fields are available to you.

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "__metadata": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "uri": {
                        "type": "string"
                    },
                    "type": {
                        "type": "string"
                    }
                }
            },
            "Author": {
                "type": "object",
                "properties": {
                    "__deferred": {
                        "type": "object",
                        "properties": {
                            "uri": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "DeletedBy": {
                "type": "object",
                "properties": {
                    "__deferred": {
                        "type": "object",
                        "properties": {
                            "uri": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "AuthorEmail": {
                "type": "string"
            },
            "AuthorName": {
                "type": "string"
            },
            "DeletedByEmail": {
                "type": "string"
            },
            "DeletedByName": {
                "type": "string"
            },
            "DeletedDate": {
                "type": "string"
            },
            "DeletedDateLocalFormatted": {
                "type": "string"
            },
            "DirName": {
                "type": "string"
            },
            "DirNamePath": {
                "type": "object",
                "properties": {
                    "__metadata": {
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string"
                            }
                        }
                    },
                    "DecodedUrl": {
                        "type": "string"
                    }
                }
            },
            "Id": {
                "type": "string"
            },
            "ItemState": {
                "type": "integer"
            },
            "ItemType": {
                "type": "integer"
            },
            "LeafName": {
                "type": "string"
            },
            "LeafNamePath": {
                "type": "object",
                "properties": {
                    "__metadata": {
                        "type": "object",
                        "properties": {
                            "type": {
                                "type": "string"
                            }
                        }
                    },
                    "DecodedUrl": {
                        "type": "string"
                    }
                }
            },
            "Size": {
                "type": "string"
            },
            "Title": {
                "type": "string"
            }
        }
    }
}

Processing Deleted Files

Once the recently deleted files have been retrieved from the Recycle Bin, the remainder of the workflow ensures that the file is temporarily restored in its original library before moving it into the custom recycle bin. Returning the file to its original location is a necessary step to retrieve the file’s content, which is not available while the file resides in the Recycle Bin.

Avoiding Infinite Looping

The first thing you need to do is add a check to see if the source library from where the file came is the custom recycle bin itself. This is done by comparing the DirName property of the current file to the name of your custom recycle bin (in my case it’s Custom Recycle Bin.) This is important as you may want to delete files from the custom recycle bin. Without this check, they will always return to the custom recycle bin.

Screenshot of Condition action to check if the DirName of the deleted file is the name of the custom Recycle Bin. If no, then the workflow continues to the subsequent steps.
Figure 5: Performing a check to see where the file came from.    Used with permission from Microsoft.

Restoring the File to Its Original Location

Now, you may ask yourself why we need to restore the file to the original location. The reason is that when a file is deleted, it is temporarily stored in a location within SharePoint Online that is not accessible to the user. Only the file name and path are accessible when accessing the deleted file from the original Recycle Bin.

Screenshot of Send an HTTP action used with the _api/web/RecycleBin(‘id’)/restore() SharePoint REST API endpoint to restore the file to its original location
Figure 6: Restoring the file from the original Recycle Bin.    Used with permission from Microsoft.

The Id in this action is passed from the Parse JSON action above that represents the unique file identifier.

Moving the File From Its Original Location to the Custom Recycle Bin

The next step is to move the file from the original location to the custom recycle bin. This is achieved using the Move file action.

 Screenshot of Move File action. The source points to the site where the file lives and the File to Move is determined by concatenating the DirName and LeafName. The destination of the file is the custom recycle bin.
Figure 7: Moving file from original location to custom recycle bin.   Used with permission from Microsoft.

The File to Move needs to include the path to the file (DirName) without the site’s part and the file name (Leafname). You can get it using the following expression:

concat(replace(items('Apply_to_each')?['DirName'],'sites/<your_site_name>',''),'/',items('Apply_to_each')?['LeafName'])

Populating the Original Location Column for the Deleted File

The last step in the workflow is to populate the Original Location column with the original location of the file. This includes the site name, library, and file path. The Original Location will allow the users to know where these files came from.

Screenshot of Update file properties action.
Figure 8: Applying the Original Location property to the file.   Used with permission from Microsoft.

Again, you can see that the DirName and LeafName properties captured earlier in the Parse JSON action are used here.

Conclusion

This solution works great when files in a specific SharePoint Online site may need to be safeguarded from accidental deletion for longer than 93 days. However, it is important to note that if the original files contain custom metadata, this approach will not capture it (although it could be modified to do so). Also, if users need to restore a file that they deleted, they would need to be trained to go to the custom recycle bin rather than the built-in Recycle Bin.

 

Haniel Croitoru

Haniel Croitoru

Haniel Croitoru is an enterprise architect and Microsoft MVP with over 20 years of experience in Microsoft 365. Since 2003, Haniel has been focusing on delivering solutions to meet short-term and long-term business goals using Microsoft 365 workloads such as SharePoint, Teams, Power Platform and more. 

In addition to Haniel’s professional tenure, he has always been a big proponent of sharing knowledge and giving back to the community through presenting at numerous conferences and networking meetings on the topics of utilizing Microsoft 365 for business process optimization, effective collaboration and communication, and managing projects using the platform. 

Prior to entering the Microsoft 365 arena, Haniel spent several years in the medical imaging industry where he helped launch an orthopedic software division and published four patents and numerous articles. 

Haniel holds a Master of Science in Computer Science with a specialty in Computer-Assisted Orthopedic Surgery from Queen’s University and a Master’s Certificate in Project Management from the York Schulich School of Business. He is a PMI-certified Project Management Professional (PMP) and Agile Certified Practitioner (PMI-ACP). 

Your Privacy

Like most sites, TekkiGurus uses cookies and similar technologies to improve your experience.

We may use cookies and other technologies that:

  • Are essential for the site to work
  • Remember your preferences
  • Collect information about how you use our site
  • Provide more relevant content and advertising
Cookie Policy