Skip To Content

示例:准备在离线工作流中使用的 Esri 底图

ArcGIS Enterprise 预先配置了来自 ArcGIS Online 的底图集合。不支持在离线工作流中使用这些底图。例如,您无法在 Collector for ArcGIS 中离线使用预配置底图。

以下 python 脚本采用默认 ArcGIS Online 底图并将其作为地图项目添加到门户中。可离线使用底图地图项目并将其用于离线工作流中。为运行脚本,您需要提供 ArcGIS Online 帐户凭据。

运行此脚本时,您需要指定以下信息:

  • 用于访问 Portal for ArcGIS 的 URL。该 URL 可以是 ArcGIS Web Adaptor URL (例如 https://webadaptorhost.domain.com/webadaptorname),也可以是托管门户的计算机 URL(例如 https://portal.domain.com:7443/arcgis)。指定 URL 时必须将计算机的完全限定域名包括在内。
  • 门户中帐户的用户名和密码。
  • 将创建新地图项目的文件夹的名称。如果未提供此文件夹,则会在您的根文件夹中创建地图项目。
  • ArcGIS Online 帐户的用户名和密码。此脚本会将您的 ArcGIS Online 凭据嵌入到新地图项目中,这将启用底图的离线功能。

以下示例将在您的根文件夹中创建底图集合。这些底图中包括您的 ArcGIS Online 凭据,这样诸如 Collector for ArcGIS 等应用程序便可在离线工作流中使用这些底图。

python prepareEsriBasemapsForOfflineUse.py https://webadaptorhost.domain.com/webadaptorname portalUser portalPassword arcGISOnlineUser arcGISOnlinePassword
#!/usr/bin/env python
# Requires Python 2.7+
# Sample Usage:
# python addOfflineBasemaps.py -u <destinationPortal> -o <portalAdmin>
#                              -s <portalPassword> -f <destFolder>
#                              -a <agoUsername> -p <agoPassword>
import urllib import json import argparse
def generateToken(username, password, portalUrl):
    '''Retrieves a token to be used with API requests.'''    parameters = urllib.urlencode({'username' : username,                                   'password' : password,                                   'client' : 'referer',                                   'referer': portalUrl,                                   'expiration': 60,                                   'f' : 'json'})    response = urllib.urlopen(portalUrl + '/sharing/rest/generateToken?',                              parameters).read()    try:
        jsonResponse = json.loads(response)        if 'token' in jsonResponse:
            return jsonResponse['token']        elif 'error' in jsonResponse:
            print jsonResponse['error']['message']            for detail in jsonResponse['error']['details']:
                print detail    except ValueError, e:
        print 'An unspecified error occurred.'        print e
def searchPortal(portal, query=None, totalResults=None, sortField='numviews',                 sortOrder='desc', token=''):
    '''    Search the portal using the specified query and search parameters.    Optionally provide a token to return results visible to that user.    '''    # Default results are returned by highest    # number of views in descending order.    allResults = []    if not totalResults or totalResults > 100:
        numResults = 100    else:
        numResults = totalResults    results = __search__(portal, query, numResults, sortField, sortOrder, 0,                         token)
    if not 'error' in results.keys():
        if not totalResults:
            totalResults = results['total'] # Return all of the results.        allResults.extend(results['results'])        while (results['nextStart'] > 0 and               results['nextStart'] < totalResults):
            # Do some math to ensure it only            # returns the total results requested.            numResults = min(totalResults - results['nextStart'] + 1, 100)            results = __search__(portal=portal, query=query,                                 numResults=numResults, sortField=sortField,                                 sortOrder=sortOrder, token=token,                                 start=results['nextStart'])            allResults.extend(results['results'])        return allResults    else:
        print results['error']['message']        return results
def __search__(portal, query=None, numResults=100, sortField='numviews',               sortOrder='desc', start=0, token=None):
    '''Retrieve a single page of search results.'''    params = {
        'q': query,        'num': numResults,        'sortField': sortField,        'sortOrder': sortOrder,        'f': 'json',        'start': start    }
    if token:
        # Adding a token provides an authenticated search.        params['token'] = token    request = portal + '/sharing/rest/search?' + urllib.urlencode(params)    results = json.loads(urllib.urlopen(request).read())    return results
def groupSearch(query, portalUrl, token=''):
    '''Search for groups matching the specified query.'''    # Example 1: query all groups owned by a user.    # 'owner:johndoe'    # Example 2: query groups with Operations in the name.    # 'Operations'    # Example 3: query all groups with public access.    # 'access:public'    parameters = urllib.urlencode({'q': query, 'token': token, 'f': 'json'})    request = (portalUrl + '/sharing/rest/community/groups?' + parameters)    groups = json.loads(urllib.urlopen(request).read())    return groups['results']
def getUserContent(username, portalUrl, token):
    ''''''    parameters = urllib.urlencode({'token': token, 'f': 'json'})    request = (portalUrl + '/sharing/rest/content/users/' + username +
               '?' + parameters)    print request    content = urllib.urlopen(request).read()    return json.loads(content)
def getItemDescription(itemId, portalUrl, token=''):
    '''Returns the description for a Portal for ArcGIS item.'''    parameters = urllib.urlencode({'token' : token,                                   'f' : 'json'})    response = urllib.urlopen(portalUrl + "/sharing/rest/content/items/" +
                              itemId + "?" + parameters).read()    return json.loads(unicode(response, 'utf-8'))
def createFolder(username, title, portalUrl, token):
    '''Creates a new folder in a user's content.'''    parameters = urllib.urlencode({'title': title,                                   'token' : token,                                   'f' : 'json'})    response = urllib.urlopen(portalUrl + '/sharing/rest/content/users/' +
                              username + '/createFolder?', parameters).read()    return json.loads(response)
def addServiceItem(username, folder, description, serviceUrl, portalUrl,                   token, thumbnailUrl='', serviceUsername=None,                   servicePassword=None):
    '''Creates a new item in a user's content.'''    # Update the description with unicode safe values.    descriptionJSON = __decodeDict__(json.loads(description))    parameters = {'item': descriptionJSON['title'],                  'url': serviceUrl,                  'thumbnailurl': thumbnailUrl,                  'overwrite': 'false',                  'token' : token,                  'f' : 'json'}
    if serviceUsername and servicePassword:
        # Store the credentials with the service.        parameters.update({'serviceUsername': serviceUsername,                           'servicePassword': servicePassword})
    # Add the item's description (with safe values for unicode).    parameters.update(descriptionJSON)
    # Encode and post the item.    postParameters = urllib.urlencode(parameters)    response = urllib.urlopen(portalUrl + '/sharing/rest/content/users/' +
                              username + '/' + folder + '/addItem?',                              postParameters).read()    return json.loads(response)
# Helper functions for decoding the unicode values in the response json. def __decodeDict__(dct):
    newdict = {}
    for k, v in dct.iteritems():
        k = __safeValue__(k)        v = __safeValue__(v)        newdict[k] = v    return newdict
def __safeValue__(inVal):
    outVal = inVal    if isinstance(inVal, unicode):
        outVal = inVal.encode('utf-8')    elif isinstance(inVal, list):
        outVal = __decode_list__(inVal)    return outVal
def __decode_list__(lst):
    newList = []    for i in lst:
        i = __safeValue__(i)        newList.append(i)    return newList
# Run the script. if __name__ == '__main__':
    parser = argparse.ArgumentParser()    parser.add_argument('-u', '--portal', required=True,                        help=('url of the Portal (e.g. '                              'https://portal.domain.com:7443/arcgis)'))    parser.add_argument('-o', '--portalAdmin', required=True,                        help='Portal admin username')    parser.add_argument('-s', '--portalPassword', required=True,                        help='Portal admin password')    parser.add_argument('-a', '--agoAdmin', required=True,                        help='ArcGIS Online admin username')    parser.add_argument('-p', '--agoPassword', required=True,                        help='ArcGIS Online admin password')    parser.add_argument('-f', '--folder', required=False,                        help='Optional destination folder')    # Read the command line arguments.    args = parser.parse_args()    agoAdmin = args.agoAdmin    agoPassword = args.agoPassword    portal = args.portal    portalAdmin = args.portalAdmin    portalPassword = args.portalPassword    folderTitle = args.folder
    # Get a token for the Portal for ArcGIS.    print 'Getting token for ' + portal    token = generateToken(username=portalAdmin, password=portalPassword,                          portalUrl=portal)
    # Get the destination folder ID.    folderId = ''    if folderTitle == None:
        # No folder specified. Folder is root.        print 'Using the root folder...'        folderId = '/'    else:
        # Check if the folder already exists.        userContent = getUserContent(portalAdmin, portal, token)        for folder in userContent['folders']:
            if folder['title'] == folderTitle:
                folderId = folder['id']        # Create the folder if it was not found.        if folderId == '':
            print 'Creating folder ' + args.folder + '...'            newFolder = createFolder(portalAdmin, folderTitle, portal, token)            folderId = newFolder['folder']['id']        print 'Using folder ' + folderTitle + ' (id:' + folderId + ')'
    # Get the ArcGIS Online group ID.    query = 'owner:esri title:Tiled Basemaps'     # Search for the public ArcGIS Online group (no token needed).    sourceGroup = groupSearch(query, 'https://www.arcgis.com')[0]['id']
    # Get the items in the ArcGIS Online group specified above.    basemaps = searchPortal('https://www.arcgis.com', 'group:' + sourceGroup)
    # Add the basemaps as new items in the Portal.    for basemap in basemaps:
        # Get the item description.        description = getItemDescription(basemap['id'],                                         'https://www.arcgis.com')        serviceUrl = description['url']        thumbUrl = ('https://www.arcgis.com' +
                    '/sharing/rest/content/items/' + description['id'] +
                    '/info/' + description['thumbnail'])
        newDescription = json.dumps(            {'title': description['title'],             'type': description['type'],             'snippet': description['snippet'],             'description': description['description'],             'licenseInfo': description['licenseInfo'],             'tags': ','.join(description['tags']),             'typeKeywords': ','.join(description['typeKeywords']),             'accessInformation': description['accessInformation']}
        )
        try:
            result = addServiceItem(portalAdmin, folderId, newDescription,                                    serviceUrl, portal, token, thumbUrl,                                    agoAdmin, agoPassword)            if 'success' in result:
                print 'Successfully added ' + basemap['title']            elif 'error' in result:
                print 'Error copying ' + basemap['title']                print result['error']['message']                for detail in result['error']['details']:
                    print detail            else:
                print 'Error copying ' + basemap['title']                print 'An unhandled error occurred.'        except:
            print 'Error copying ' + basemap['title']            print 'An unhandled exception occurred.'
    print 'Copying complete.'