Agregar la Url de un adjunto a la tabla o capa

2961
2
10-03-2019 11:18 AM
OscarSolis1
Esri Contributor
2 2 2,961

En algunas ocasiones puede ser necesario tener adjuntos como una imagen multimedia en la ventana emergente de nuestro mapa web o web app, sin embargo, esto se ve imposibilitado ya que los adjuntos no se muestran en un campo como si fuese un hipervínculo. Es posible escribir la dirección manualmente en un campo ya que por medio del rest podríamos saber cómo es esta, que básicamente es así: https//direcion del servidor/rest/services/Hosted/nombre del servicio/número de la capa o tabla dentro del servicio/objectid/attachments/objectid del adjunto.

Pero esto es algo ideal si nuestro servicio estuviera compuesto de pocos registros sería una tarea sencilla, y la realidad es que normalmente manejamos cientos o miles de datos, es por eso, que les presento a continuación algo que me encontré en este vínculo: URL link to Attachment Photo when the FeatureLayer is not Shared with Everyone  gracias a John Evans‌ . 

Antes de continuar es necesario que sepan que en la capa o tabla donde se encuentren los adjuntos debe existir un campo de texto donde almacenar la URL del Adjunto, en este caso yo creé un campo llamado imageurl en las tablas donde tengo los adjuntos. Este está declarado en el Script como 'imageurl' así que si ustedes poseen otro campo donde almacenar la url simplemente cambian eso en el script de python.

Primero que nada deben entender como funcionan los servicios en ArcGIS Online y en Portal. Son similares pero existen un par de diferencias, empezando porque en Portal todos los campos de los Hosted Services están en minúscula, lo cual no sucede en ArcGIS Online.

Empecemos con el rest, ya les mencioné como va pero acá un ejemplo. lo que vamos a hacer es mostrar los detalles del servicio que marqué.

Al acceder a los detalles es importante que observen el id que tiene dicho servicio, este es un identificador único y para el script es de vital importancia.

Ahora otro concepto básico que necesitan saber es la url del rest, si observan bien, más abajo en la página podrán ver que tenemos dos secciones una de capas y otra de tablas, en cada una de ellas tenemos acciones que permiten activar o realizar ciertas tareas, pero la que nos atañe es la que dice URL de servicio, pueden acceder a cualquiera pero deben de tomar en cuenta que la URL de cada capa o tabla es distinta, por otro lado, la que nos interesa para nuestro objetivo es la capa o tabla que tiene los adjuntos, en mi caso es la tabla (¿qué cómo lo sé? pues basta con observar que en capas dice "Habilitar adjuntos", o sea no tiene y en la tabla dice "Deshabilitar adjuntos" en otras palabras esta es la que tiene lo que necesitamos).

En este caso ingresaré a la de capas solamente para que observen algo que es importante, por lo tanto al ingresar a URL de servicio, nos lleva acá.

En dicha imagen marqué dos cosas, la primera es donde podemos devolvernos al servicio que contiene todas las capas y tablas, y en segundo lugar el ID de la capa, ahora daré clic sobre el servicio para ver el contenido de este y poder ver el ID de todas las capas y tablas que componen el servicio.

En esta sección en la parte inferior podemos ver las capas y tablas:

En mi caso, tengo 1 capa y 2 tablas, su respectivo Id sería:

  • 0 para la capa
  • 1 para la primera tabla (esta tiene adjuntos)
  • 2 para la segunda tabla (también tiene adjuntos)

Si ingresamos a cualquiera de las tablas que tienen adjuntos podrán observar esto al final de la página:

Notarán que existe un enlace que sirve para consultar  (Query) ahora ingresaré en ese enlace y podremos consultar la información.

Básicamente sólo le consulte where: 1=1 que siempre es verdadero y Return IDs Only para nada más ver los objectids de la tabla.

Finalmente solo presioné el botón Query Get

Y.... este es el resultado

En esta tabla solamente existen 4 registros, si dan clic a cualquier object id podrán ver la información de dicho registro. Algo así:

Verán que existe un enlace que dice Attachment Infos, si acceden ahí verán si existen adjuntos

ahora si observan el nombre de la imagen es otro enlace, al dar clic pueden obtener la URL de dicha imagen:

Por lo tanto sería para ambos casos (ArcGIS Online o Portal) https://urldelrestdelfeatureservice/numerodecapaotabla/objectid/attachments/objectid 

Importante destacar que es importante de saber que orden ocupa su capa o tabla dentro del servicio, por ejemplo en mi casa tenía lo siguiente:

Layer {0}

Tabla {1}

Tabla {2}

Por lo tanto, tengo dos cosas una el ID que es el número que se puede observar y lo otro es el número de orden en layer como tengo solamente un valor el número de orden es 0, en las tablas la primera es 0 y la segunda es 1 de acuerdo al número de orden. Esto es importante para la línea field_service_layer = (field_service.layers) donde tenemos que escribir el número de orden correspondiente.

Todo lo anterior ha sido para que se entienda que es lo que hace el siguiente script:

import arcpy
from arcgis import GIS
import pandas as pd
import time
from copy import deepcopy

# Connect to FAASYSOPS Portal
oursite = GIS("url del portal o de arcgis online","usuario", "contraseña")

#Update the image field
def UpdateImageField() :

    # init some stuff
    features_to_be_updated = []
    field_service_dataframe = ''

    try :
       
        # Get Field Service Layer (not the view layer)
        field_service = oursite .content.get('id del servicio')
        field_service_layer = (field_service.layers)[Número de la capa o tabla de acuerdo al orden]

        # Build Data Frame
        field_service_dataframe = pd.DataFrame.spatial.from_layer(field_service_layer)

        # Iterate through dataframe.
        for row in field_service_dataframe.iterrows() :
            if (row[1]['imageurl'] == None or row[1]['imageurl'] == '') :
                # Get ObjectID and set image URL
                objID = str(row[1]['objectid'])
                img_url = "urloftheview_View/FeatureServer/ID de capa o tabla/{0}/attachment/{0}".format(objID)

                # init feature and get feature from service
                feature_to_update = ''
                feature = field_service_layer.query(where='OBJECTID = ' + objID)

                # Make a deep copy so we keep our attributes/structure and update data
                feature_to_update = deepcopy(feature.features[0])

                # Make Field Update
                feature_to_update.attributes['imageurl'] = img_url
                features_to_be_updated.append(feature_to_update)

        if len(features_to_be_updated) != 0 :
            field_service_layer.edit_features(updates = features_to_be_updated)
    except :
        print ('Error making update. Do some real error catching or something.')

while True :
    UpdateImageField()
    time.sleep(15)

En este ejemplo se ve con una capa geográfica, pero si los adjuntos están en una tabla (como los repeats de survey) cambie esta línea   field_service_layer = (field_service.layers)[Número de la capa o tabla de acuerdo al orden] por esta   field_service_layer = (field_service.tables)[Número de la capa o tabla de acuerdo al orden]. Nota: es la línea 31 del script.

Este script una vez ejecutado no se detiene, por lo que sería bueno dejarlo ejecutando en un servidor, si lo desean detener deben hacerlo manualmente.

Una vez que hagan eso solamente deben abrir el servicio en el mapa web, y si los adjuntos se encuentran en la capa pues solamente configuran en la ventana emergente y en contenido multimedia agregan una imagen.

En la siguiente ventana agregan el campo que contiene la Url del adjunto, en mi caso es imageurl

Después clic en Aceptar y de nuevo en Aceptar. Ahora bien si los adjuntos se encuentran en tablas relacionadas como en mi caso, pues configuran la ventana emergente en la tabla o tablas relacionadas de la misma forma que se hace con una capa.

Una vez que terminen la configuración de las ventanas emergentes podrán ver las imágenes en sus webapps de la siguiente forma (en mi caso estoy usando web app buider)

Nota: dependiendo de la velocidad de Internet que tengan puede ser que la imagen no se vea automáticamente, por lo que deberán tener un poco de paciencia.

Espero que les sea de utilidad.....

2 Comments
DanielPérez_López
New Contributor III

Hola.

Gran post! me ha servido de gran ayuda pero tengo un problema con la url que devuelve el script de Python. 

En mi caso toda la arquitectura la tengo montada sobre ArcGis Online y cada foto es un registro de la tabla (mi proyecto viene de un Survey123 donde recojo las fotos dentro de una tabla por los repeats). 

Los enlaces donde están alojadas las fotos son de la forma:

https://{NOMBRE_SERVICIO}/arcgis/rest/services/{NOMBRE_SERVICIO}/FeatureServer/2/....{OBJECT ID}/att...{ATTACH_ID}

Por lo que he podido comprobar (al menos en mi caso) es que el Object_ID NO tiene por qué ser el mismo que el ATTACH_ID y entiendo que debe ser porque se han borrado fotos, hay más de una foto que se hace en el Survey.

¿Te ha ocurrido alguna vez?

Se me ocurre listar todos los Attachments en un bucle y sacar el Attach_Id, que en el caso de esta foto sería el id: 295

Input. 

dict = tabla.attachments.get_list(oid=296)
dict

Output

[{'id': 295,
  'globalId': '***********',
  'parentGlobalId': '*******',
  'name': '***********',
  'contentType': 'image/jpeg',
  'size': 1030687,
  'keywords': 'fotos',
  'exifInfo': None}]

Es un diccionario por lo que supongo que podré sacar ese dato y componer la url

https://{NOMBRE_SERVICIO}/arcgis/rest/services/{NOMBRE_SERVICIO}/FeatureServer/2/296/attachments/295

¿Alguna idea? Gracias de antemano

OscarSolis1
Esri Contributor

Hola! muchas gracias por el interés. La verdad no he tenido ese problema, pero tienes razón al haber eliminado algún adjunto queda disparejo. En Survey123 las relaciones se dan por GlobalID, por lo que en la tabla relate deberías de tener un campo llamado RelGlobalID o ParentGlobalID. Me gusta tu idea de la lista, gracias por eso. Estaré investigando en como puedo mejorar el script.

Saludos!