Ich bin häufig auf Fragen zum Herunterladen von Anhängen (z. B. Bilder und Dokumente) aus ArcGIS Online Feature Layers gestoßen. Ziel ist es, eine alternative Lösung zu dem derzeit angebotenen bereitzustellen.<\/P>
<\/P>
Erstens werden Anhänge beim Exportieren von Daten über ArcGIS Online nur dann einbezogen, wenn als Dateiformat eine File Geodatabase exportiert wird. Der Grund dafür ist, dass die File Geodatabase das einzige Format ist, das verwandte Datensätze unterstützt. Daher lautet die häufigste Antwort zum Zugriff auf Feature Layer-Anhänge außerhalb von ArcGIS Online, den Feature Layer als File Geodatabase zu exportieren und die Daten mit einem Skript wie diesem<\/A> über ArcGIS Desktop zu extrahieren. Es gibt auch ein Sync-Skript<\/A>, das eine lokale File Geodatabase mit einem gehosteten Feature Layer synchronisieren kann. Diese funktionieren gut, sind jedoch auf ArcGIS Desktop angewiesen und im Fall der ersten Option müssen Sie die File Geodatabase (die mit zunehmenden Daten wachsen kann) vor dem Ausführen des Skripts herunterladen.<\/P><\/P>Aus diesem Grund habe ich ein Skript mit der neuen ArcGIS API for Python<\/A> erstellt, das unabhängig von ArcGIS Desktop funktioniert. Tatsächlich arbeitet es direkt mit einem Web GIS, sodass Sie nicht einmal eine File Geodatabase herunterladen müssen, um auf Ihre Anhänge zuzugreifen. Es kann regelmäßig erneut ausgeführt werden und lädt nur neue Anhänge auf die Festplatte herunter, wenn diese noch nicht zuvor heruntergeladen wurden.<\/P><\/P>Was macht dieses Skript?<\/STRONG><\/P><\/P>Erstellt einen Ordner, in dem Feature-Anhänge gespeichert werden (z. B. Attachment Downloads)<\/LI>Innerhalb dieses Ordners wird für jede Ebene im angegebenen Feature Layer ein Unterordner erstelltWenn die Variable AttachmentStorage auf 'GroupedFolder<\/SPAN>' gesetzt ist, werden Anhänge im Format ObjectId-AttachmentId-OriginalFileName in einem einzigen Ordner gespeichert<\/LI>Wenn die Variable AttachmentStorage auf 'IndividualFolder' gesetzt ist, wird für jedes Feature mit Anhang ein neuer Ordner erstellt (benannt nach der Objekt-ID des Features), während die Anhänge im Format AttachmentId-OriginalFileName darin gespeichert werden<\/LI><\/OL><\/LI>Wenn der Anhang bereits auf der Festplatte vorhanden ist, wird er nicht erneut heruntergeladen<\/LI>Zusammenfassung der Downloads (Gesamtanzahl der Downloads und Gesamtgröße der Anhänge) wird als abschließende Konsolenausgabe bereitgestellt<\/LI><\/OL><\/P>Wie richten Sie es ein?<\/STRONG><\/P><\/P>Befolgen Sie den ArcGIS API for Python Installations- und Einrichtungsleitfaden<\/A>Wenn Sie Anaconda verwenden, können Sie die .yml-Datei verwenden, um die entsprechende Umgebung zu erstellen<\/LI><\/OL><\/LI>Wenn Sie die Startup.bat-Datei verwenden, bearbeiten Sie diese (in einem Texteditor), um auf die entsprechenden Ordner zu verweisen<\/LI>Sobald Sie ein Jupyter Notebook geöffnet haben, fügen Sie die angehängte .zip-Datei an einem zugänglichen Ort ein (und entpacken sie)<\/LI>Öffnen Sie die Datei DownloadAttachments.ipynb über Jupyter Notebooks und führen Sie sie aus (klicken Sie in den Code und drücken Sie Strg+Enter)<\/LI>Das Skript läuft auf dem angegebenen öffentlichen Feature Layer und lädt die Anhänge in den angegebenen Downloads-Ordner herunter<\/LI>Bei jedem Ausführen des Skripts wird eine zugehörige Protokolldatei im Logging-Ordner erstellt<\/LI><\/OL><\/P>Hinweise:<\/STRONG><\/P><\/P>Aktualisieren Sie die Variable FeatureLayerId<\/SPAN>, um das Skript für Ihren eigenen Feature Layer auszuführen<\/LI>Geben Sie Ihren PortalUserName und PortalPassword an, falls der Feature Layer gesichert ist<\/LI>Die Namen der Ordner werden gefiltert, sodass nur 0-9 und a-Z Zeichen angezeigt werden<\/LI>Dieses Skript wurde nicht gegen ArcGIS Enterprise getestet (nur Feature Layers, die in ArcGIS Online gehostet werden), sollte aber dennoch funktionieren<\/LI>Der Code ist auch über das Esri developer-support GitHub Repository<\/A> verfügbar<\/LI>}
Aus diesem Grund habe ich ein Skript mit der neuen
Was macht dieses Skript?<\/STRONG><\/P><\/P>Erstellt einen Ordner, in dem Feature-Anhänge gespeichert werden (z. B. Attachment Downloads)<\/LI>Innerhalb dieses Ordners wird für jede Ebene im angegebenen Feature Layer ein Unterordner erstelltWenn die Variable AttachmentStorage auf 'GroupedFolder<\/SPAN>' gesetzt ist, werden Anhänge im Format ObjectId-AttachmentId-OriginalFileName in einem einzigen Ordner gespeichert<\/LI>Wenn die Variable AttachmentStorage auf 'IndividualFolder' gesetzt ist, wird für jedes Feature mit Anhang ein neuer Ordner erstellt (benannt nach der Objekt-ID des Features), während die Anhänge im Format AttachmentId-OriginalFileName darin gespeichert werden<\/LI><\/OL><\/LI>Wenn der Anhang bereits auf der Festplatte vorhanden ist, wird er nicht erneut heruntergeladen<\/LI>Zusammenfassung der Downloads (Gesamtanzahl der Downloads und Gesamtgröße der Anhänge) wird als abschließende Konsolenausgabe bereitgestellt<\/LI><\/OL><\/P>Wie richten Sie es ein?<\/STRONG><\/P><\/P>Befolgen Sie den ArcGIS API for Python
Hinweise:<\/STRONG><\/P><\/P>Aktualisieren Sie die Variable FeatureLayerId<\/SPAN>, um das Skript für Ihren eigenen Feature Layer auszuführen<\/LI>Geben Sie Ihren PortalUserName und PortalPassword an, falls der Feature Layer gesichert ist<\/LI>Die Namen der Ordner werden gefiltert, sodass nur 0-9 und a-Z Zeichen angezeigt werden<\/LI>Dieses Skript wurde nicht gegen ArcGIS Enterprise getestet (nur Feature Layers, die in ArcGIS Online gehostet werden), sollte aber dennoch funktionieren<\/LI>Der Code ist auch über das
Was anyone able to name the individual attachment folders by an attribute other than objectID? I've been struggling with this for awhile.
@DanielAragon1 @JoshVan_Vlack Did you ever figure out how to include in the image name a field form the feature layer?
DanielPérez_López
I'm getting this as well, the code is executing but the files don't seem to exist in the folder? Did you resolve this?
INFO:__main__:Summary: 28 new files have been downloaded totalling 19.588373MB in size INFO:__main__:Summary: 0 attachments already existed so were not downloaded again
Hey it always works so slowly or maybe i should run the code in other environment? Im using Jupyter Notebook and in 10 minutes only 7 photos got downloaded.
Awesome, thank you for sharing your script! After adding the "[0]'s" in row 123 and 137 it worked like a charm. I havent changed anything else yet for getting an attribute value for the folder names or anything else. Already happy with this step. Thanks again!
Hi Michael.
We used your script from time to time with great success.But lately it stops with an error.
Any ideas?
Thank you 🙂
Hi Michael, I'm hoping to use this script a lot, but I've got an error that's popping up and I'm not sure how to resolve it. I'm fairly new to Python, so I'm trying to learn as I go.
As when I look into that file, below is what it's showing. Any help with what I can do to fix it?
@tk060161 Since this is using the Python API, you would have to perform some sort of attribute query. You can run this in the ArcGIS Pro python window if you would like. In the highlighted code snippet, you would just need to construct a SQL query statement that mimics the selection you were making in ArcGIS Pro.
@MattAdamssnippet above shows how to get attachments based on an attribute field query. Is it possible to do this based on a selected feature in Pro?
Hello @LuanGaspar ,
Sorry for the late response, I have added another loop to repeat the downloads for all tables as well:
for itable in range(len(itemObject.tables)): # featureTable = itemObject.tables[itable]
Then you can repeat the same thing you do for the layers
Hello @Felicitychun ,
Did you improve the script to download attachments from related table too ? If so, could you share with us?
I'm look for way to export all attachments from the survey feature and repeats tables as well on a single script.
Hello,
Great script! I am just wondering if it is at all possible to modify the name of each individual folder based on an attribute within the layer?
Thanks!
@Felicitychun Thank you for your response! It seems that your suggestion resolved that error.
Now when I run the script, it seems to feed me back the code, and the file path I tried to feed the attachments in was empty.
I really appreciate any response! A newbie to python and trying to improve!
@MichaelKelly
Hi @Anonymous User
looks like 'false' there in your code is not in brackets as a string so is trying to refer to a variable that has not been defined. In python I believe the keyword for the boolean true/false is with a capital: False
Hi anyone interested, thought I'd post my solution to my question above,
I've gotten my parent global ids using this line:
featureGuIds = featureLayer.query(where=featureFilter,out_fields=['globalid','objectid'], as_df=True,return_geometry=False)
And then I could get it when I iterate through to get the attachments as well as the object id:
currentObjectId = featureGuIds['objectid'][j] parentGlobalId = featureGuIds['globalid'][j]
Hi,
So I got the Jupyter Notebook open, I saved the attachment, and went in to customize the code to my needs. Ran the code and got this error:
NameError Traceback (most recent call last)<ipython-input-2-17b343b15353> in <module>9 "start_time": "2017-08-16T09:06:05.091046Z"10 },---> 11 "scrolled": false12 },13 "outputs": [
NameError: name 'false' is not defined
I'm trying to figure this out in the mean time, but please let me know if you can help me.
Hi @MichaelKelly ,Thanks for this, it's great!
I'm wanting to build the attachment table at the same time to get the relationships so I need the parentGlobalID. Mine doesn't have that available though:
for k in range(len(currentObjectIdAttachments)): attachmentGlobalId = currentObjectIdAttachments[k]['globalId'] attachmentParentGlobalId = currentObjectIdAttachments[k]['parentGlobalId'] attachmentId = currentObjectIdAttachments[k]['id'] attachmentName = currentObjectIdAttachments[k]['name'] attachmentSize = currentObjectIdAttachments[k]['size']
and Global ID is 'globalid' instead of 'globalID'any pointers on how do we get it from the feature as we iterate through?
Cheers
You are a lifesaver!!!!! That worked perfectly. I had been trying to figure that out for hours.... Thank you so much!
Yes! I was able to do this by using the highlighted query.
Is there a way to only download some attachments based on an attribute field? I want to be able to put in a specific project name and just download the attachments from that project (so I'm downloading 20 attachments instead of 1500). I tried this for the query (ProjectName is an attribute in my feature layer):
featureObjectIds <SPAN class="" style="color: #a67f59; background: rgba(255, 255, 255, 0.5); border: 0px; font-weight: inherit;">=</SPAN> featureLayer<SPAN class="" style="color: #999999; border: 0px; font-weight: inherit;">.</SPAN>query<SPAN class="" style="color: #999999; border: 0px; font-weight: inherit;">(</SPAN>where<SPAN class="" style="color: #a67f59; background: rgba(255, 255, 255, 0.5); border: 0px; font-weight: inherit;">=ProjectName</SPAN><SPAN class="" style="color: #669900; border: 0px; font-weight: inherit;"> == <SPAN style="color: #333333; background-color: #f7f7f7;">'9858C</SPAN>'</SPAN><SPAN class="" style="color: #999999; border: 0px; font-weight: inherit;">,</SPAN> return_ids_only<SPAN class="" style="color: #a67f59; background: rgba(255, 255, 255, 0.5); border: 0px; font-weight: inherit;">=</SPAN><SPAN class="" style="color: #990000; border: 0px; font-weight: inherit;">True</SPAN><SPAN class="" style="color: #999999; border: 0px; font-weight: inherit;">)</SPAN>
But then I got this error:
NameError: name 'ProjectName' is not defined Is there any way to do this?
Try using a service Item ID that you are familiar with. Like one that is in your own AGOL organization do not try using the default Item ID. The error you are getting is basically saying it is not finding a feature service based on the ID you are giving it.
The weird thing is I am just running the script as I downloaded it so wondering if the service that was set up for testing has now been taken down? Have you gotten the script to run recently? Maybe there are other changes that have happened that are causing the script to fail?
You may not be calling the feature correctly, the message says you have no name attribute
AttributeError: 'NoneType' object has no attribute 'name'
This script looks promising but I not sure I am set up to run it properly... Currently I am Right clicking on the original "DownloadAttachments.py" and then running "Edit with IDLE (ArcGIS Pro)" then Run > Run Module. This is what I get:
Python 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 14:00:49) [MSC v.1915 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license()" for more information.>>> ================== RESTART: C:\Temp\DownloadAttachments.py ==================INFO:__main__:Script Starting at 2020-06-09 18:11:08.674435ERROR:arcgis._impl.connection:Item does not exist or is inaccessible.Traceback (most recent call last): File "C:\Temp\DownloadAttachments.py", line 77, in <module> logger.info('Iterating through layers in Feature Layer "{}"'.format(itemObject.name))AttributeError: 'NoneType' object has no attribute 'name'
I have left all of the configuration stuff alone and was trying to just see if I could get the test data to work...
Any suggestions for a novice?
Hi, everybody.I followed the post to download the attached photos from a survey I generated (the photos are inside a table).I have also modified the script because I had the same problem as @Chelsea Rozek
I'm running the script inside the ArcGis Online Notebook.It doesn't give me any error and it seems to download the content. However I go to the path where the downloaded photos are supposed to be but the folder doesn't exist. Although the script is saying that the photos are downloaded.
INFO:__main__:Time: 2020-06-08 10:44:57.796204 INFO:__main__:Currently looping through feature attachments in layer 1 of 2: storing in folder named "0-foto" INFO:__main__:There are 386 features to iterate in this layer INFO:__main__:The size of the current attachment being downloaded is 1.17647MB ----------
INFO:__main__:C:\ScriptDownloads\\0-foto\\103/fotos-20200525-132307.jpg being renamed as C:\ScriptDownloads\\0-foto\\103\103-fotos-20200525-132307.jpg INFO:__main__:The size of the current attachment being downloaded is 1.69949MB
Any suggestions? Thanks
Michael Kelly Thanks for this script! I'm using it for a few applications and it works great! Recently I implemented a survey123 app that captures pictures in a repeat, and so images are attached to a related table. Can this script be modified to download attachments from related tables, or is does it need to be from the feature layer?
Hello Michael Kelly. Thank you fo putting script together and sharing it with the Community. I forked your project in Github. I'm working on adding capabilities the Community is requesting here and will submit a commit soon. Plus I am adding the ability to choose a portal that is Enterprise or AGO, and some other automation.
As for saving each attachment with a file name using an attribute value I am running into an issue with the FeatureSet object that is returned from Query() I am passing in the currentObjectId to obtain the field containing the pole number, which is esupportstructure_facilityid.
currentObjectId <SPAN class="operator token">=</SPAN> featureObjectIds<SPAN class="punctuation token">[</SPAN><SPAN class="string token">'objectIds'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN>j<SPAN class="punctuation token">]</SPAN> facilityID <SPAN class="operator token">=</SPAN> featureLayer<SPAN class="punctuation token">.</SPAN>query<SPAN class="punctuation token">(</SPAN>objectids<SPAN class="operator token">=</SPAN>currentObjectId<SPAN class="punctuation token">,</SPAN> outFields<SPAN class="operator token">=</SPAN><SPAN class="string token">'esupportstructure_facilityid'</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
The documentation appears to return a JSON object so I also tried treated it as such. When I do that another error appears as attached below,
FeatureSet' object is not subscriptable
I have not found any ArcGIS Python API examples that work with FeatureSet object and Query(), can you point to some samples or provide a snippet.
---------------------------------------------------------------------------TypeError Traceback (most recent call last)<ipython-input-1-bc6c83cbc278> in <module> 202 currentObjectId = featureObjectIds['objectIds'][j] 203 facilityID = featureLayer.query(objectids=currentObjectId, outFields='esupportstructure_facilityid')--> 204 poleNumber = facilityID['eSupportStructure_FACILITYID'] 205 logger.info(f'{poleNumber}') 206 currentObjectIdAttachments = featureLayer.attachments.get_list(oid=currentObjectId)TypeError: 'FeatureSet' object is not subscriptable
JSON Response from Query().
INFO:__main__:{"features": [{"geometry": {"x": 2678790.012921214, "y": 236090.84788563848}, "attributes": {"eSupportStructure_FACILITYID": "47185"}}], "objectIdFieldName": "OBJECTID", "globalIdFieldName": "GlobalID", "spatialReference": {"wkid": 102660, "latestWkid": 2238}, "geometryType": "esriGeometryPoint", "fields": [{"name": "eSupportStructure_FACILITYID", "alias": "Pole Number", "type": "esriFieldTypeString", "length": 20}]}
this worked for me too (ie just adding [0] on line 123, and line 137, so that the line is
renameFile(currentAttachmentPath[0], newAttachmentPath)
instead of
renameFile(currentAttachmentPath, newAttachmentPath)
- I am running python 3.7.2, so it seems to be an issues that comes up when using a later version of python
Is the feature layer you're running this on publicly accessible? If yes, what's the url?
I did that step and this error popped up.
Sounds like Holly's error above, see my previous response for a solution: adding [0] to the end of the currentAttachmentPath variable
Angemeldete Mitglieder können Beiträge verfassen, Updates folgen und mehr. Neu hier? Registrieren Sie ein kostenloses Konto.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.