As many of you are aware, shortly (winter ’18) Salesforce will require all of its users to use Files as they are phasing out Attachments and Notes. While Salesforce is doing a nice job of releasing a tool in Summer ’17 to handle conversion of Attachments to Files, they still have not handled how to mass download all attachments from the system. This may be important to your org before going through the conversion process (or for any other reason). I know it is for mine.
My business case is actually two-fold:
- I need to get all of the attachments into a safe place before we do the conversion
- I need to get all of a specific type of attachment downloaded so that it can be uploaded elsewhere
While Salesforce does provide admins with the Data Export tool, the tool itself has a significant number of limitations. First and foremost, you can only run it once a week. Second, it downloads the files without the extensions and without the attachment name, essentially rendering them useless (at least for me). Lastly, you have zero control over which attachments are downloaded. In fact, since it is just a single checkbox option, you will get stuck downloading all attachments, documents, and files and that could lead to more headaches than anyone cares to deal with.
So with all of that said, I wrote up a nice design spec explaining what I was looking for and handed it off to my partner, who translated my design spec into a Python utility, and which is now available for all on GitHub.
The script is relatively straightforward. It goes through all of the attachments and downloads them to your local computer. The tool preserves the original filename and prefixes it with its Attachment ID. For my second business use case, I only needed attachments that were on Accounts, so an extra option exists to download Accounts Only attachments (by default it will download ALL attachments). As a bonus, there’s an option to ignore file names that contain certain keywords.
The script also creates a CSV file that maps the Parent ID to the attachment filename, so you could easily tell which file is associated with which account.
How to use the script:
- Make sure you have Python and pip installed
- Install simple-salesforce and requests
$ pip install simple-salesforce
$ pip install requests
- Download the tool from GitHub
- Open your CLI (Terminal/CMD) and run the following line:
$ attachments_downloader.py -u [SFDC username] -p [SFDC password] -t [SFDC token] -s [Path to Store Attachments]
- (Optional) If you want to download attachments belonging to Account only:
$ attachments_downloader.py -u [SFDC username] -p [SFDC password] -t [SFDC token] -s [Path to Store Attachments] --account-only
- (Optional) If you want to skip certain attachments:
$ attachments_downloader.py -u [SFDC username] -p [SFDC password] -t [SFDC token] -s [Path to Store Attachments] --ignore WORD1 WORD2 ...
Here’s a real-world example:
$ attachments_downloader.py -u sf9to5@example.com -p password -t sf9to5_super_secret_token -s /tmp/ --account-only --ignore photo demo upload
The command line above will download all attachments that belong to Account only and will skip any files which contain “photo”, “demo” or “upload” in their name.
Troubleshooting:
- We tested it on Windows and macOS (Sierra) only (should work on Linux too)
- Ensure your macOS has the most recent OpenSSL library (use brew to upgrade) and that Python uses the most recent OpenSSL library. This is required for the tool to talk TLS with Salesforce
- Works on Production environments only
- Of course, make sure your user has the right permissions 🙂
Link to Mass Attachments Downloader tool:
https://github.com/ysfdc/salesforce_scripts/blob/master/attachments_downloader.py
I would love to get your feedback on whether you find this useful and if you have any questions. Thanks!
Good thinking to backup your attachments before attempting the conversion. I also developed an open source project to assist with migrating from Attachments to Files using batchable apex: https://douglascayers.com/2015/10/10/salesforce-convert-attachments-to-chatter-files/
LikeLike
Nice work, looks like a great tool. Am I reading this right though that it can only get attachments from the Account object?
LikeLike
Hi Matt, The tool works for downloading either all attachments in the org or specifically on attachments on the Account object. We will later be adding functionality to support other specific objects.
LikeLike
Error: when executing python code
File “attachments_downloader.py”, line 18
except Exception, e:
^
SyntaxError: invalid syntax
LikeLike
Are you using Python3 to run it?
The script was developed for Python 2.
LikeLike
I installed python 2 and is executing fine. Thanks..! Nice job.
Have you implemented this in salesforce itself (Apex & Visulaforce)?
After downloading Id is getting added to the filename. I want like Id should be after filename or Id should not be there in filename.
LikeLike
I have not implemented it in Salesforce. You can modify the code to change the location or remove the id.
LikeLike
i am getting the simmilar error.
LikeLike
This is fantastic sf9t05. Is there a limit where if we want to download 50k attachments will it be feasible?
LikeLike
I believe so, though it will depend on your org’s API call limit. The most I have done is between 10-15K.
LikeLike
You may want to try out an app that i came across on appexchange called “Mass File Download”. Mass File Download appexchange app help you Download Multiple Files on a single click. It supports Mass download of Attachments, Files, Static Resource and Documents as a zip throughout the organization on record level. Checkout app @ https://goo.gl/tCHD5F
LikeLiked by 1 person
Do you know if the app works in Classic and if it gives you the parent record ID for attachments?
LikeLike
Mass File Download app works in both Classic and Lightning. Also, it downloads the actual file.
LikeLike
Along with actual files/attachments being downloaded, MFD appexchange app also gives you a CSV mapping file containing Parent ID, Owner, Created, LastModifiedDate, etc metadata details of files being downloaded
LikeLike
When do you plan to release MDA V2? Thanks.
LikeLike
What are you looking for in V2? I don’t currently have it on the roadmap.
LikeLike
One simple app is there on salesforce called “Mass file Download”. This app Download Multiple Files on a single click. It supports Mass download of Attachments, Files, Static Resource and Documents as a zip throughout the organization on record level.
https://appexchange.salesforce.com/listingDetail?listingId=a0N3A00000EcsAOUAZ
LikeLike
Does it keep the ID of the original record the attatchment was associated to? The tool I created appends this to the file name.
LikeLike
Yes the MFD app does give you an option to download files with the original file name and file ID. Also, you can download the file name containing any parent record field value as well. Also, an additional CSV is downloaded along with files containing N rows (where N is No of files being downloaded). Each row contains meta-information about the file such as file id, parent id, parent name, last modified, etc.
LikeLike
I would like to use this for a client but would like to provide an LOE. Can you provide an estimate for 31k attachments and 200k notes? (For notes, we would update the scripts so that it pulls from that object)Thanks!
LikeLike
Hi Clara, can you email me with more information of what you are looking for from me? Thanks
LikeLike
Hi! I sent you an email! Thanks
LikeLike
Hi, is there a chance that this works in test? I’ve seen that the url used for the request is login.salesforce.com
LikeLike
The script works with Sandbox, but you would need to do some code changes. If you refer to our wrapper class https://github.com/ysfdc/salesforce_scripts/blob/master/sfdc.py you can see that it uses a YAML configuration file to specify if it’s a sandbox or not. This should be relatively quick to adjust the current code to use the sfdc.py module.
LikeLike
Thanks for the reply! Can you please provide more details as I’m haven’t used Python and just a beginner? I’ll still try to figure it out.
LikeLike
You can try https://www.sfdcfileexporter.com/sffxhome/
LikeLike
Hi sf9to5,
We have re written code in python 3, but I am able to download only 2000 Attachments at a time.
I am not sure what I am doing wrong. But I have a task to download about 250K attachments from my Org.
Is there a way to achieve 10-15 K as you mentioned above.
Regards
Sumit Datta
LikeLike
What changes to be made to have access to sandbox org? Requesting for your help.
LikeLike
The script works with Sandbox, but you would need to do some code changes. If you refer to our wrapper class https://github.com/ysfdc/salesforce_scripts/blob/master/sfdc.py you can see that it uses a YAML configuration file to specify if it’s a sandbox or not. This should be relatively quick to adjust the current code to use the sfdc.py module.
LikeLike
Thanks a lot sf9to5. I was able to figure out the changes for sandbox login. Thank you once again.
LikeLike
Hello, thank you for creating this article/tool. I have around 101 thousand attachments in my PROD org and would like to download them. I have followed the steps as you have described but when I run it in command line, nothing happens. I have provided the Username, Password and Security Token. In the command line it says:
Starting downloader…
Done.
but, when I go to the folder, there are no attachments. I am absolutely new to python. Would you be able to help?
Thank you,
Adil
—
LikeLike
Hi sf9to5,
Attachment Download is working as Expected but sizes for each file are 10.3KB and I am not able to open files after Download is complete. I tried downloading only 10 records and file size is 10.3KB again. Any help is appreciated.
LikeLike
Unfortunately, I no longer have any orgs that have or support attachments to test your particular scenario.
LikeLike
Hello sf9to5,
Thanks for this amazing tool!
Can you please help me in having access to the SF org which is SSO enabled. The present code supports only for org having username and password. It would great if I hear any suggestion or advice from you to satisfy the above requirement.
Thanks Again!!
LikeLike
I am running the command:
$ attachments_downloader.py -u [my u/n] -p [my psw] -t [my token] -s C:\Python –opportunity-only
and I receive error:
$’ is not recognized as an internal or external command,
operable program or batch file.
Then I remove the $ and I run it. once I run it a pop up window comes asking me which application I want this to run with.
There I guess I need to select spyder/visual studio etc to run it.
If I select the python.exe it does not do anything.
When I select the visual studio, then the application launches.
Do I just need to execute the script in visual studio and some time after this the files will be exported on the defined path?
LikeLike
This tool would be much more useful if we could specify a list of attachments we wanted to download. We are in need of a tool to download a subset of attachments (maybe 10,000 out of millions of attachments – we don’t want to download them all or download account attachments only.
LikeLike
Hello,
This is a really helpful tool. I stumbled upon this very recently and was able to try it out. This works fine but only for limited no. of records.
Currently, I have 100k + attachment records to be exported and somehow the tool stops after processing 2k records. Is there anything you are aware causing this?
Thanks in advance!
LikeLike
You may have a look to https://nicolas.vuillamy.fr/how-to-mass-download-notes-and-attachments-files-from-a-salesforce-org-83a028824afd to manage an unlimited number of records & files ^^
LikeLike
I’ve used this tool a dozen times and have had great success, thank you! Just recently tried to use it again after a few months and am now receiving the error “SyntaxError: multiple exception types must be parenthesized” when trying to call the python script from Powershell.
Has there been a recent change in python, simple_salesforce, or salesforce directly that would now make the callout using un/pw/security token inaccessible?
LikeLike
I have not had the chance to update this to Python 3, from Python 2 – this is likely a syntax error due to that.
LikeLike