Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Si vous continuez à utiliser ce dernier, nous considèrerons que vous acceptez l'utilisation des cookies. J'ai compris ! ou En savoir plus !.
banniere

Le portail francophone de la géomatique


Toujours pas inscrit ? Mot de passe oublié ?
Nom d'utilisateur    Mot de passe              Toujours pas inscrit ?   Mot de passe oublié ?

Annonce

Pour sa 21ème année, l’association GeoRezo a toujours besoin de vous !

10€ = 1 mois de frais bancaires ; 15€ = 12 mois de nom de domaine ; 30€ = 1 semaine de location des serveurs …

Faire un don 

Retrouver nos membres bienfaiteurs

#1 Wed 17 January 2024 09:17

Tetranos
Participant occasionnel
Date d'inscription: 21 Sep 2020
Messages: 16

API de téléchargement de la Geoplateforme et BDTOPO

Bonjour à tous,

Je travaille actuellement à l'automatisation du téléchargement du dernier millésime de la BDTOPO France métropolitaine au format SQL.

J'utilise pour cela l'API de téléchargement dont la documentation est disponible au lien ci-après et je développe en Python : https://geoservices.ign.fr/services-geo … chargement

Grâce à l'API, j'arrive à lister les produits, les différents jeux de données (millésimes) de chacun des produits puis sur un jeu de données spécifique, je parviens à lister les fichiers associés.

Le problème se pose au moment du téléchargement, par exemple avec cette URL : https://data.geopf.fr/telechargement/do … 15.7z.001.

S’agissant de fichiers volumineux (4Go), j'ai testé les différentes versions de code proposées ici : https://www.alixaprodev.com/download-la … -requests/ pour ne pas avoir à monter tout le fichier en RAM.

Après lancement du téléchargement, l'erreur suivante se produit : Connection broken: IncompleteRead(62905 bytes read)



J'ai fait différents tests pour tenter de comprendre d'où pouvait venir le problème mais n'ai pas encore trouvé de solutions.

Test 1 : le téléchargement du fichier via Firefox fonctionne.

Test 2 : le téléchargement par code Python du fichier ne fonctionne pas que je sois sur mon réseau perso ou d'entreprise.

Test 3 : le téléchargement par code Python d'un plus petit fichier (par exemple la BDTOPO en GPKG d'un département) fonctionne.

Test 4 : le téléchargement par code Python d'un fichier volumineux sur un autre site (une distribution Linux de 4Go) fonctionne.

Test 5 : le téléchargement par code Python de la BDTOPO via les anciennes URL (https://wxs.ign.fr/859x8t863h6a09o9o6fy … -15.7z.001) fonctionne.

Test 6 : l'utilisation de requests.post au lieu de requests.get ne fonctionne pas car le service ne l'autorise pas.



Je n'y connais pas grand chose en protocole HTTP, mais je remarque que les headers qui sont renvoyées sont différents entre les anciennes et les nouvelles URL.

L'ancienne URL indique un content-type à "application/octet-stream" et donne le content-length. La nouvelle URL indique un content-type en "application/json" ainsi que content-disposition à "attachment; filename="BDTOPO_3-3_TOUSTHEMES_SQL_LAMB93_FXX_2023-09-15.7z.001" mais n'indique pas de content-length.

En fait, j'ai l'impression que la connexion se coupe avant la fin du téléchargement du fichier. Peut-être faut-il que j'ajoute des entêtes dans la requête HTTP d'appel...

Voici la fonction :

Code:

def download_file(url: str, file_path: str, verify_ssl = True):
    """
    Télécharge un fichier par bloc.
    Si le fichier existe localement, il est écrasé.
    
    url : L'URL du fichier à télécharger.
    file_path : Le chemin d'enregistrement du fichier.
    verify_ssl : Vrai pour activer la vérification SSL, faux sinon.
    """
    with requests.get(url, stream = True, verify = verify_ssl) as response:
        response.raise_for_status()

        for key, value in response.headers.items():
            print(key, "=", value)
            
        with open(file_path, 'wb') as file:
            shutil.copyfileobj(response.raw, file)

Et un exemple d'appel :

Code:

download_file("https://data.geopf.fr/telechargement/download/BDTOPO/BDTOPO_3-3_TOUSTHEMES_SQL_LAMB93_FXX_2023-09-15/BDTOPO_3-3_TOUSTHEMES_SQL_LAMB93_FXX_2023-09-15.7z.001", "c:/temp/BDTOPO.7z")

Merci de votre aide.

PS : j'ai également publié cette même question sur la communauté Géoplateforme OSMOSE.
PPS : j'ai trouvé sur un site un message de quelqu'un qui avait un problème similaire et qui à contourner en utilisant curl via un subprocess...ce que je préfèrerais éviter.

Hors ligne

 

#2 Wed 17 January 2024 15:09

cquest
Participant assidu
Date d'inscription: 6 Jan 2013
Messages: 875

Re: API de téléchargement de la Geoplateforme et BDTOPO

Je pense que ça n'a pas de rapport avec les entêtes qui n'ont que peu d'importance ici.

Je ne suis pas habitué à télécharger de gros fichiers avec python mais il me semble que c'est plutôt la façon de récupérer le fichier qui n'est pas cohérente entre le stream=True et l'utilisation de response.raw

Avec stream=True (qui est la bonne façon de télécharger un gros fichier), il faut ensuite avoir une boucle de réception qui va recevoir petit à petit le fichier et l'enregistrer au fur et à mesure sur disque.

Voir: https://realpython.com/python-download- … ng-fashion


subprocess c'est une façon d'utiliser depuis python des outils en ligne de commande comme curl ou wget pour télécharger le fichier, ce qui est moins portable. Je l'utilise assez souvent, mais du coup le code a souvent du mal à tourner sous Windows.


Christian Quest - https://amicale.net/@cquest sur Mastodon (terminé twitter/X)
Membre fondateur et porte parole d'OpenStreetMap France
Initiateur de opendatArchives, OpenEventDatabase, Panoramax

Hors ligne

 

#3 Wed 17 January 2024 15:31

Tetranos
Participant occasionnel
Date d'inscription: 21 Sep 2020
Messages: 16

Re: API de téléchargement de la Geoplateforme et BDTOPO

Bonjour Christian,

La version avec la boucle et le "chunk" est en effet également proposée dans le lien que j'ai cité.

J'ai même trouvé 2 déclinaisons, avec ou sans if (chunk) préalablement à l'appel au write : https://stackoverflow.com/questions/166 … h-requests

Mais cette solution donne sensiblement le même résultat :
Connection broken: InvalidChunkLength(got length b'', 0 bytes read)

C'est noté pour les headers, et pour le subprocess c'est bien pour cela que je voudrais éviter. Je crée une petite boîte à outils et j'aimerais pouvoir l'utiliser aussi bien sur mon poste (Windows) que sur le serveur de traitement auto (Linux).

Merci

Dernière modification par Tetranos (Wed 17 January 2024 15:33)

Hors ligne

 

#4 Wed 17 January 2024 16:03

cquest
Participant assidu
Date d'inscription: 6 Jan 2013
Messages: 875

Re: API de téléchargement de la Geoplateforme et BDTOPO

Plus léger avec urllib que requests:

Code:

from urllib.request import urlretrieve

url = 'http://mirror.pnl.gov/releases/16.04.2/ubuntu-16.04.2-desktop-amd64.iso'
dst = 'ubuntu-16.04.2-desktop-amd64.iso'
urlretrieve(url, dst)

Christian Quest - https://amicale.net/@cquest sur Mastodon (terminé twitter/X)
Membre fondateur et porte parole d'OpenStreetMap France
Initiateur de opendatArchives, OpenEventDatabase, Panoramax

Hors ligne

 

#5 Wed 17 January 2024 16:12

Tetranos
Participant occasionnel
Date d'inscription: 21 Sep 2020
Messages: 16

Re: API de téléchargement de la Geoplateforme et BDTOPO

J'ai testé cette technique aussi mais ça bug pareil.

Hors ligne

 

Pied de page des forums

Powered by FluxBB