# Télécharger les fichiers uploadés par un usager sur son dossier

{% hint style="info" %}
**Nous recommandons de paralléliser / asynchroniser le téléchargement des fichiers**. En effet, un dossier peut avoir de nombreuses PJ, qui elle même peuvent peser jusqu'a 200Mo.&#x20;
{% endhint %}

{% hint style="danger" %}
Attention, les liens vers **les fichiers expirent au bout de 1h**.
{% endhint %}

Pour ajouter les URLs des fichiers à votre code existant, Il vous faut ajouter le `FileFragment` au `ChampFragment` :

```graphql
  fragment ChampFragment on Champ {
    ... on PieceJustificativeChamp {
      files {
        ...FileFragment
      }
    }
  }
  
  fragment FileFragment on File {
    filename
    contentType
    checksum
    byteSize: byteSizeBigInt
    url
  }
```

Vous pouvez tester en executant le script suivant avec les variables d'environnement adaptées :

<pre class="language-bash"><code class="lang-bash"><strong>API_TOKEN="votre_token" DEMARCHE_NUMBER=votre_numero_de_demarche ruby downloader.rb
</strong></code></pre>

Pour faciliter la lecture du code, la query complète GraphQL est fournie en PJ

{% file src="<https://463284772-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-L7_aKvpAJdAIEfxHudA%2Fuploads%2FbEIL1LYUFsSffrMaOqks%2FgetDemarche.listOnlyFilesUrl.graphql?alt=media&token=c34fc857-8410-48d6-aab3-927464a71bdf>" %}
query GraphQL minimaliste pour lister les type de champs Piece Justificative ainsi que les fichiers associéés
{% endfile %}

Ensuite, vous pouvez executer ce code ruby

{% code title="downloader.rb" %}

```ruby
require 'net/http'
require 'uri'
require 'json'
ENDPOINT = URI('https://demarche.numerique.gouv.fr/api/v2/graphql')

### that's the GraphQL part.
# We store the query in a flat file because it's easier to read
def query
  File.read("getDemarche.listOnlyFilesUrl.graphql")
end

### that's the HTTP part
# open an http connexion to our GraphQL endpoint
def open_http_connection
  http = Net::HTTP.new(ENDPOINT.host, ENDPOINT.port)
  http.use_ssl = true
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
  http
end

# the headers of our http query, include auth
def request_headers
  {
    "Content-Type" => "application/json",
    "Authorization" => "Bearer #{ENV['API_TOKEN']}"
  }
end

# given an http connexion, request the API for page
def request_page(http)
  # the data of our query
  data = {
    "query" => query,
    "operationName" => "getDemarche",
    "variables" => {
      "demarcheNumber": ENV['DEMARCHE_NUMBER'].to_i,
      "first": 100
    }
  }

  req = Net::HTTP::Post.new(ENDPOINT, request_headers)
  req.body = data.to_json

  response = http.request(req)

  data = JSON.parse(response.body)
  data
end

http = open_http_connection
# check if we persisted a cursor so we continue polling
data = request_page(http)

dossiers = data.dig('data', 'demarche', 'dossiers', 'nodes')
puts "Info: fetched dossiers ids: #{dossiers.map{ _1['number'] }.join(', ')}"

all_champs = dossiers.flat_map { |dossier| dossier['champs'] }
all_champs_pj = all_champs.filter { |champ| champ['files'] }
all_url_to_download = all_champs_pj.flat_map { |pj| pj['files'].map{ |file| file['url'] } }

puts "Info: now you can download each of those url: #{all_url_to_download.join(', ')}"

```

{% endcode %}
