Using the python script below it seems that I can request the generation of tile packages from an ESRI ArcMap REST service, and then download the resulting tpk file generated by ESRI. But when I try and open the package NOTHING shows up in ArcMap. Can't tell what is happening - can't tell what is going wrong. Any ideas?

import arcpy
import requests
import pandas as pd
import time
import json

def gen_token():
    arcpy.SignInToPortal_server("USERNAME", "PASSWORD", "")
    token = arcpy.GetSigninToken()
    return str(token['token'])

def check_status(jobID, token):
    req_status_url = 'http://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Topo_Map/MapServer/jobs/' \
                     + jobID \
                     + '?f=json' \
                       '&token=' + token

    status_resp = requests.get(req_status_url)
    status_resp_cont = json.loads(status_resp.content)
    return str(status_resp_cont['jobStatus'])

def scrape_tiles(input_file, levels):

    token = gen_token()

    tpk_grid_df = pd.read_csv(input_file, header=0)

    for index,row in tpk_grid_df.iterrows():

        extent = '{"xmin":' + str(row['XMIN']) + \
                 ',"ymin":'+str(row['YMIN']) + \
                 ',"xmax":'+str(row['XMAX']) + \
                 ',"ymax":'+str(row['YMAX']) + \
                 ',"spatialReference" : {"wkid" : 4326}}'

        req_url = 'http://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Topo_Map/MapServer/exportTiles?' \
                  'tilePackage=true' \
                  '&exportExtent=' + extent + \
                  '&optimizeTilesForSize=true' \
                  '&compressionQuality=90' \
                  '&exportBy=levelId' \
                  '&levels=' + str(levels) + \
                  '&f=json' \
                  '&token=' + token

        resp = requests.get(req_url)
        resp_cont_dic = json.loads(resp.content)
        jobID = str(resp_cont_dic['jobId'])
        jobStatus = str(resp_cont_dic['jobStatus'])

        while jobStatus == 'esriJobSubmitted' or jobStatus == 'esriJobExecuting':
            jobStatus = check_status(jobID, token)

        if jobStatus == 'esriJobFailed':

        res_url = 'http://tiledbasemaps.arcgis.com/arcgis/rest/services/World_Topo_Map/MapServer/jobs/' \
                  + str(jobID) \
                  + '/results/out_service_url?f=json' \
                    '&token=' + token

        result_resp = requests.get(res_url)
        result_resp_cont_dic = json.loads(result_resp.content)
        result_url = result_resp_cont_dic['value'] + '/Layers.tpk'

        file_name = 'NH_TP_' + str(levels) + '_' +  str(row['ID']) + '.tpk'

        r = requests.get(result_url)
        with open(file_name, 'wb') as f:
            for chunk in r.iter_content(chunk_size=1024):
                if chunk:  # filter out keep-alive new chunks
                    f.flush() #commented by recommendation from J.F.Sebastian

if __name__ == "__main__":

    input_file = "TPK_Grid_100.csv"
    num_levels = 17
    scrape_tiles(input_file, num_levels)

First couple of lines from the input file:

1   -72.573919  42.633528   -72.37901   42.909766
2   -72.37901   42.633528   -72.1841    42.909766
  • I've worked with groups trying this, they were not successful, it works for a few tiles but considering Esri uses a composite service it's tough. Most of services are scale dependent and as you zoom in it will get data from another service. You can see this when you zoom all the way in and then back out a little, the image changes. Not to mention the cached levels of imagery, you would need hundreds of GBs of space and a fast server to use it. It ended up easier to use their servers as they were faster. For arcPad we just used screen captures as jpegs. – Bill Chappell May 22 '17 at 14:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.