ArcGIS Online フィーチャ レイヤーから添付ファイル(例:写真やドキュメント)をダウンロードする方法に関する質問をよく受けます。これの目的は、現在提供されている方法に代わるソリューションを提供することです。<\/P>
<\/P>
まず、ArcGIS Online でデータをエクスポートする際に添付ファイルが含まれる唯一の方法は、ファイル ジオデータベースとしてエクスポートする場合です。その理由は、ファイル ジオデータベースが関連レコードをサポートする唯一の形式だからです。したがって、ArcGIS Online 以外でフィーチャ レイヤーの添付ファイルにアクセスする最も一般的な回答は、フィーチャ レイヤーをファイル ジオデータベースとしてエクスポートし、スクリプトを使ってデータを抽出することです。こちらのようなスクリプト<\/A>を ArcGIS Desktop を通じて使用します。また、同期スクリプト<\/A>もあり、ローカルのファイル ジオデータベースとホストされたフィーチャ レイヤーを同期できます。これらはうまく機能しますが、ArcGIS Desktop に依存しており、オプション1の場合はスクリプト実行前にファイル ジオデータベース(データ追加によりサイズが大きくなる可能性があります)をダウンロードする必要があります。<\/P><\/P>このため、新しい ArcGIS API for Python<\/A> を使ったスクリプトを作成しました。これは ArcGIS Desktop とは独立して動作します。実際には Web GIS と直接連携するため、添付ファイルにアクセスするためにファイル ジオデータベースをダウンロードする必要すらありません。このスクリプトは定期的に再実行でき、以前にダウンロードされていない新しい添付ファイルのみをディスクにダウンロードします。<\/P><\/P>このスクリプトは何をするのか?<\/STRONG><\/P><\/P>フィーチャ 添付ファイルを保存するフォルダー(例:Attachment Downloads)を作成します<\/LI>このフォルダー内に指定されたフィーチャ レイヤーの各レイヤーごとにサブフォルダーを作成しますAttachmentStorage 変数が 'GroupedFolder<\/SPAN>' に設定されている場合、添付ファイルは ObjectId-AttachmentId-OriginalFileName の形式で単一フォルダー内に保存されます<\/LI>AttachmentStorage 変数が 'IndividualFolder' に設定されている場合、添付ファイルがある各フィーチャごとに新しいフォルダー(フィーチャの Object ID を名前として)を作成し、その中に AttachmentId-OriginalFileName の形式で添付ファイルが保存されます<\/LI><\/OL><\/LI>添付ファイルが既にディスク上に存在する場合は再度ダウンロードしません<\/LI>ダウンロードの概要(合計ダウンロード数と合計添付ファイルサイズ)が最終コンソール出力として提供されます<\/LI><\/OL><\/P>セットアップ方法は?<\/STRONG><\/P><\/P>ArcGIS API for Python の インストールとセットアップ<\/A> ガイドに従いますAnaconda を使用している場合は .yml ファイルで適切な環境を作成できます<\/LI><\/OL><\/LI>Startup.bat ファイルを使用している場合は(テキストエディタで)適切なフォルダー参照に編集します<\/LI>Jupyter Notebook が開いたら、下記の添付 .zip ファイルをアクセス可能な場所に貼り付け(解凍してください)ます<\/LI>Jupyter Notebooks で DownloadAttachments.ipynb ファイルを開き実行します(コード内クリック後 Ctrl+Enter 押下)<\/LI>スクリプトは指定された公開フィーチャ レイヤー上で動作し、指定された Downloads フォルダーへ添付ファイルをダウンロードします<\/LI>スクリプト実行時には Logging フォルダー内に関連ログ ファイルが作成されます<\/LI><\/OL><\/P>注意事項:<\/STRONG><\/P><\/P>FeatureLayerId 変数を更新してご自身のフィーチャ レイヤーで実行してください<\/LI>フィーチャ レイヤーがセキュアな場合は PortalUserName, PortalPassword を指定してください<\/LI>フォルダー名は 0-9 と a-Z の文字のみ表示されるようフィルターされています<\/LI>このスクリプトは ArcGIS Enterprise(ArcGIS Online にホストされたフィーチャ レイヤーのみ対象)ではテストされていませんが、それでも動作するはずです<\/LI>コードは Esri developer-support GitHub リポジトリ からも入手可能です<\/LI><\/UL><\/BODY><\/HTML>
このため、新しい
このスクリプトは何をするのか?<\/STRONG><\/P><\/P>フィーチャ 添付ファイルを保存するフォルダー(例:Attachment Downloads)を作成します<\/LI>このフォルダー内に指定されたフィーチャ レイヤーの各レイヤーごとにサブフォルダーを作成しますAttachmentStorage 変数が 'GroupedFolder<\/SPAN>' に設定されている場合、添付ファイルは ObjectId-AttachmentId-OriginalFileName の形式で単一フォルダー内に保存されます<\/LI>AttachmentStorage 変数が 'IndividualFolder' に設定されている場合、添付ファイルがある各フィーチャごとに新しいフォルダー(フィーチャの Object ID を名前として)を作成し、その中に AttachmentId-OriginalFileName の形式で添付ファイルが保存されます<\/LI><\/OL><\/LI>添付ファイルが既にディスク上に存在する場合は再度ダウンロードしません<\/LI>ダウンロードの概要(合計ダウンロード数と合計添付ファイルサイズ)が最終コンソール出力として提供されます<\/LI><\/OL><\/P>セットアップ方法は?<\/STRONG><\/P><\/P>ArcGIS API for Python の
注意事項:<\/STRONG><\/P><\/P>FeatureLayerId 変数を更新してご自身のフィーチャ レイヤーで実行してください<\/LI>フィーチャ レイヤーがセキュアな場合は PortalUserName, PortalPassword を指定してください<\/LI>フォルダー名は 0-9 と a-Z の文字のみ表示されるようフィルターされています<\/LI>このスクリプトは ArcGIS Enterprise(ArcGIS Online にホストされたフィーチャ レイヤーのみ対象)ではテストされていませんが、それでも動作するはずです<\/LI>コードは
Hi Holly - have you ever got this script working before? I have not replicated this behaviour with the version of the Python API included with ArcGIS Pro 2.1.2 (v1.2.5). Can you test with the FeatureLayerId = '092d075f4b3a40f78cf1329b20b0d5e7' - this is a public layer so you should be able to access.
I initially wrote this using v1.2.0 of the ArcGIS API for Python - I have not tested it with later versions.
Hi Michael, thanks for this post...very useful!
I am trying to download a feature layer created by a Survey123 application that allows users to capture multiple photos per record. To do so we had to build it as a relationship. Here is the URL: https:[host]/portal/home/item.html?id=f0dcf24f2bb9440d9fa2c8ec64141fe1#data. When viewing the Data tab from the Portal I can select the "(0) Add" text in the "Photos and Files" field to access the photos. I tried plugging f0dcf24f2bb9440d9fa2c8ec64141fe1#data into the FeatureLayerID =, but it returns no files. Any idea what I may be missing?
Hi Eric,
If the photos are stored in a table with no spatial attributes, it will appear as a table through the API (as opposed to a layer). Therefore the 'layers' text in lines 81/82/96 have to be chanced to 'tables'.
<SPAN class="comment token">#Lines 81/82</SPAN> <SPAN class="keyword token">for</SPAN> i <SPAN class="keyword token">in</SPAN> range<SPAN class="punctuation token">(</SPAN>len<SPAN class="punctuation token">(</SPAN>itemObject<SPAN class="punctuation token">.</SPAN>tables<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> featureLayer <SPAN class="operator token">=</SPAN> itemObject<SPAN class="punctuation token">.</SPAN>tables<SPAN class="punctuation token">[</SPAN>i<SPAN class="punctuation token">]</SPAN> <SPAN class="punctuation token">.</SPAN><SPAN class="punctuation token">.</SPAN><SPAN class="punctuation token">.</SPAN> <SPAN class="comment token">#Line 96</SPAN> logger<SPAN class="punctuation token">.</SPAN>info<SPAN class="punctuation token">(</SPAN><SPAN class="string token">'Currently looping through feature attachments in layer {} of {}: storing in folder named "{}"'</SPAN><SPAN class="punctuation token">.</SPAN>format<SPAN class="punctuation token">(</SPAN>str<SPAN class="punctuation token">(</SPAN>i <SPAN class="operator token">+</SPAN> <SPAN class="number token">1</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> str<SPAN class="punctuation token">(</SPAN>len<SPAN class="punctuation token">(</SPAN>itemObject<SPAN class="punctuation token">.</SPAN>tables<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">,</SPAN> featureLayerName<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
This should loop through any associated tables (as opposed to layers) and return the appropriate results.
Kind regards,
Mikie
That was exactly what I needed! Thanks so much!
Hey Mike,
The script is running as expected, but I am trying to get it to place the attachments in a folder named after a value specified by a specific field ("Subject") in the related layer. Do you have any pointers for how to configure that?
Thanks!
Eric
Hi Eric - a similar question came through in one of the comments above. You would have to alter the query to send back the appropriate attributes, and then use the returned attributes whilst specifying the associated file name.
I can't carry out this program because the following error happens. Please tell me the solution.
My feature layer comprises Japanese words. So this error may happen.
Is this program applicable to Japanese layers?
File "C:\ProgramData\Anaconda3\lib\http\client.py", line 1117, in putrequest self._output(request.encode('ascii'))
UnicodeEncodeError: 'ascii' codec can't encode characters in position 43-45: ordinal not in range(128)
Hi Holly,
I was getting the same error as you. I fixed it by adding [0] to the end of the currentAttachmentPath variable so that it gets the first and only attachment path in that list and uses it. I had to add it to this part: renameFile(currentAttachmentPath[0], newAttachmentPath) under both GroupedFolder and IndividualFolder. I tested it on Michael's public layer, and was able to download the attachments.
Thank you very much.
I'll try it.
2018年7月6日(金) 3:08 Chelsea Rozek <geonet@esri.com>:
GeoNet <https://community.esri.com/?et=watches.email.document_comment>Downloading Feature Layer Attachments via the ArcGIS API for Pythonnew comment by Chelsea Rozek<https://community.esri.com/people/rozekc_washtenaw?et=watches.email.document_comment> Viewall comments on this document<https://community.esri.com/docs/DOC-10441-downloading-feature-layer-attachments?commentID=63017&et=watches.email.document_comment#comment-63017>
GeoNet <https://community.esri.com/?et=watches.email.document_comment>
Downloading Feature Layer Attachments via the ArcGIS API for Python
new comment by Chelsea Rozek
<https://community.esri.com/people/rozekc_washtenaw?et=watches.email.document_comment> View
all comments on this document
<https://community.esri.com/docs/DOC-10441-downloading-feature-layer-attachments?commentID=63017&et=watches.email.document_comment#comment-63017>
Hi 竹元 貴彦,
Did you get the script working with the pre-set public layer? I have not tested this against layers with Japanese. Does the layer itself (layer name, field names, etc.) contain Japanese, or is there Japanese only in the attributes? Is the layer available publically, or could you share it with me through a group? My ArcGIS Online username is mikie.kelly.
Mikie,
This is an awesome script and I was able to get it working quickly despite limited Python experience. I am wondering how line 92 might be modified to fetch GUIDs instead of OIDs.
I worked using private layer. So I can't show it imediately. I make or search another layer that contains Japanese to show you the problem as soon as possible.
My private layer has Japanese both field name and attributes.
Hi Bob,
Global ID's are returned with the attachments. You can access them by adding to lines 108-111 as below (both attachment Global ID and attachment parent Global ID accessible):
<SPAN class="keyword token">for</SPAN> k <SPAN class="keyword token">in</SPAN> range<SPAN class="punctuation token">(</SPAN>len<SPAN class="punctuation token">(</SPAN>currentObjectIdAttachments<SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> attachmentGlobalId <SPAN class="operator token">=</SPAN> currentObjectIdAttachments<SPAN class="punctuation token">[</SPAN>k<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'globalId'</SPAN><SPAN class="punctuation token">]</SPAN> attachmentParentGlobalId <SPAN class="operator token">=</SPAN> currentObjectIdAttachments<SPAN class="punctuation token">[</SPAN>k<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'parentGlobalId'</SPAN><SPAN class="punctuation token">]</SPAN> attachmentId <SPAN class="operator token">=</SPAN> currentObjectIdAttachments<SPAN class="punctuation token">[</SPAN>k<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'id'</SPAN><SPAN class="punctuation token">]</SPAN> attachmentName <SPAN class="operator token">=</SPAN> currentObjectIdAttachments<SPAN class="punctuation token">[</SPAN>k<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'name'</SPAN><SPAN class="punctuation token">]</SPAN> attachmentSize <SPAN class="operator token">=</SPAN> currentObjectIdAttachments<SPAN class="punctuation token">[</SPAN>k<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">[</SPAN><SPAN class="string token">'size'</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
Then you can reference them when naming the file 117
fileName = '{}-{}-{}'.format(attachmentGlobalId, attachmentParentGlobalId, attachmentName)<SPAN class="line-numbers-rows"><SPAN></SPAN></SPAN>
Works like a charm. Thanks.
Great script. I would also appreciate having the attachment files named based on a field in the associated attribute table. You mentioned this is possible but would require some rejigging -- have you or anyone else developed script for this?
Annalise
Hi Annalise,
I'm afraid not, at least not that I'm aware of.
I work with the U.S. Fish and Wildlife Service and use an Enterprise Account login. Can this script function with an Enterprise login?
#What are your ArcGIS Enterprise/ArcGIS credentials? This is case sensitive.PortalUserName = 'email here'PortalPassword = 'password here'PortalUrl = 'https://fws.maps.arcgis.com'
I changed the PortalURL to direct to the FWS ArcGIS URL but I keep getting an error message -- [ERROR:arcgis._impl.connection:Invalid username or password.]
I've confirmed that the username and password I entered are correct.
https://fws.maps.arcgis.com is an address for ArcGIS as opposed to ArcGIS Enterprise. All ArcGIS accounts can simply use https://www.arcgis.com for the PortalUrl. An ArcGIS Enterprise address is likely to look like this: https://portalcomputer.domain.com/portal/home.
PortalUserName = 'MKelly@MyDomain'
PortalPassword = 'MyPassword'
PortalUrl = 'https://portalcomputer.domain.com/portal/home'
Further information can be found here. One thing to note is that the username can be case sensitive - you need to replicate how it appears in the Portal organisation page.
Hi Michael
Great script, quick question: Is it possible to get a file-like object from the attachments manager without downloading the file locally first?
So instead of downloading the file with attachments.download i would want to have the attachment as an in-memory object...
Currently my script first downloads the attachment and then opens it into a binary file-like object and then delete the local file when i am done....
Any help will be appreciated.
Hi Deon,
I haven't noticed anything like that in the AttachmentManager class - is there a problem with the approach you are currently taking?
get_list includes the URL of any attachments (from what I remember) if that's any use?
Hi Michael Kelly,
A couple of days ago our machines were upgraded to ArcGIS Pro 2.2.1 (Python 3.6.5).
Since then attachments fail to include "OBJECTID - ATTACHMENTID" in the attachment file names (only attachment names).
Can you think of the reason for this - from the top of your head? Otherwise, I'm more than happy to take a further look.
But I thought I'd ask you first.
Thanks,
Gee
All sorted.
It was the same error as what Holly Tran was experiencing. And managed to get it working by using Chelsea Rozek's suggestion.
Thanks guys,
Getting this error with enterprise. Anyone have a possible solution?
Sounds like Holly's error above, see my previous response for a solution: adding [0] to the end of the currentAttachmentPath variable
I did that step and this error popped up.
Is the feature layer you're running this on publicly accessible? If yes, what's the url?
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
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}]}
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?
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
サインインしたメンバーは投稿、更新のフォローなどができます。初めてですか?無料アカウントを登録してください。
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.