Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Neste quickstart, constrói uma aplicação web que apresenta imagens de satélite e dados geoespaciais do seu GeoCatálogo num mapa interativo. Autentica os utilizadores com o Microsoft Entra ID, consulta coleções STAC e renderiza blocos de mapas — tudo a partir do JavaScript do navegador.
O que aprende:
- Autentique utilizadores e adquira tokens de acesso usando MSAL.js
- Consulte a API STAC para descobrir coleções e itens
- Mostrar blocos raster num mapa MapLibre GL com cabeçalhos de autorização
- Crie camadas de mosaico sem costuras ao longo de coleções inteiras
- Descarregue ativos brutos usando tokens SAS
Os padrões de código funcionam com qualquer framework JavaScript moderno (React, Vue, Angular) ou JavaScript simples. As APIs do GeoCatalog têm suporte total para CORS, por isso podê-las chamar diretamente de localhost durante o desenvolvimento — sem necessidade de proxy.
Pode descarregar e testar este código a partir do repositório público do Microsoft Planetary Computer Pro no GitHub.
Pré-requisitos
- Uma conta do Azure com uma assinatura ativa. Crie uma conta gratuitamente.
- Um recurso GeoCatalog implementado com pelo menos uma coleção contendo itens.
- A sua identidade de utilizador deve ter acesso GeoCatalog Reader (ou superior) ao recurso GeoCatalog. Consulte Gerir acesso a um recurso GeoCatalog.
- Node.js versão 18 ou posterior.
Visão geral da arquitetura
Uma aplicação web típica do GeoCatalog segue esta arquitetura:
Registe a sua candidatura no Microsoft Entra ID
Antes de a sua aplicação web autenticar utilizadores, registe-a no Microsoft Entra ID. Este início rápido utiliza um registo de Aplicação de Página Única (SPA ), ideal para aplicações JavaScript do lado do cliente e desenvolvimento local. Os padrões de integração da API apresentados em etapas posteriores funcionam com qualquer tipo de aplicação.
Observação
Para aplicações de produção com servidor backend, considere escolher um tipo de registo diferente (Web, Nativo, etc.). Consulte Configurar autenticação de aplicações para orientações sobre como escolher a abordagem certa para o seu cenário.
Registar como uma aplicação de página única
- Vá ao Microsoft Entra ID no portal Azure.
- Selecione registos de aplicações no painel lateral.
- Selecione Novo registo.
- Insira um nome para a sua candidatura (por exemplo, "GeoCatalog Web App").
- Em Tipos de conta suportados, selecione Contas somente neste diretório organizacional.
- Em Redirecionar URI, selecione Aplicação de página única (SPA) e introduza o seu URL de desenvolvimento (por exemplo,
http://localhost:5173). - Selecione Register.
Após o registo, note os seguintes valores da página de Visão Geral :
- ID do aplicativo (cliente)
- ID da diretoria (tenant)
Para mais informações, consulte o registo na aplicação de início rápido.
Conceder permissões API
A sua aplicação precisa de permissão para chamar a API GeoCatalog em nome dos utilizadores com sessão iniciada:
- No registo da sua aplicação, selecione permissões API Adicionar>uma permissão.
- Seleciona as APIs que a minha organização usa e pesquisa por Azure Orbital Spatio.
- Selecione permissões delegadas e verifique user_impersonation.
- Selecione Adicionar permissões.
- Se for administrador, selecione Conceder consentimento de administrador em nome de todos os utilizadores do seu inquilino.
Configure a sua aplicação
A sua aplicação precisa dos seguintes valores de configuração. A forma como fornece estes valores depende das suas ferramentas de construção (variáveis de ambiente, ficheiros de configuração, e assim por diante):
| Configuração | Valor | Description |
|---|---|---|
| URL do catálogo | https://{name}.{region}.geocatalog.spatio.azure.com |
O seu endpoint GeoCatalog |
| ID do inquilino | A partir do registo da aplicação | O seu inquilino Microsoft Entra |
| ID do Cliente | A partir do registo da aplicação | ID de cliente da sua aplicação |
| Âmbito API | https://geocatalog.spatio.azure.com/.default |
Use sempre este valor exato |
Instalar dependências
Instale a Microsoft Authentication Library (MSAL) para aplicações de navegador e uma biblioteca de mapas:
npm install @azure/msal-browser maplibre-gl
- @azure/msal-browser - Gere a autenticação OAuth 2.0 com a Microsoft Entra ID
- maplibre-gl - Biblioteca de mapas open source para visualização de mosaicos
Sugestão
Estrutura do projeto: Os exemplos de código neste quickstart são funções autónomas que podes organizar como preferires. Um padrão comum:
-
auth.js: Configuração MSAL e funções de token -
api.js: Funções de STAC API, Tiler API e SAS token -
map.js: A inicialização do MapLibre e a gestão da camada de mosaicos -
App.jsoumain.js: Conecta tudo à tua interface de utilizador
Cada função recebe as suas dependências (tokens de acesso, URLs) como parâmetros, tornando-as fáceis de integrar em qualquer framework ou estrutura de projeto.
Implementar autenticação MSAL
Configure o MSAL para autenticação do navegador. O exemplo seguinte mostra a configuração da chave e o padrão de aquisição de tokens:
import { PublicClientApplication, InteractionRequiredAuthError } from '@azure/msal-browser';
// Configuration - replace with your values or load from environment/config
const msalConfig = {
auth: {
clientId: 'YOUR_CLIENT_ID',
authority: 'https://login.microsoftonline.com/YOUR_TENANT_ID',
redirectUri: window.location.origin,
},
cache: {
cacheLocation: 'sessionStorage',
storeAuthStateInCookie: false,
},
};
// Create MSAL instance
const msalInstance = new PublicClientApplication(msalConfig);
// GeoCatalog API scope - always use this exact value
const scopes = ['https://geocatalog.spatio.azure.com/.default'];
/**
* Acquire an access token for GeoCatalog API calls.
* Tries silent acquisition first, falls back to popup if needed.
*/
async function getAccessToken() {
const account = msalInstance.getActiveAccount() || msalInstance.getAllAccounts()[0];
if (!account) {
throw new Error('No authenticated account. Call login() first.');
}
try {
// Try silent token acquisition (uses cached token)
const result = await msalInstance.acquireTokenSilent({ account, scopes });
return result.accessToken;
} catch (error) {
// If silent fails (token expired), fall back to popup
if (error instanceof InteractionRequiredAuthError) {
const result = await msalInstance.acquireTokenPopup({ scopes });
return result.accessToken;
}
throw error;
}
}
/**
* Sign in the user via popup.
*/
async function login() {
const result = await msalInstance.loginPopup({ scopes });
msalInstance.setActiveAccount(result.account);
return result.account;
}
/**
* Sign out the user.
*/
function logout() {
msalInstance.logoutPopup();
}
API STAC: Consultar coleções e itens
A API STAC do GeoCatalog fornece pontos finais para descobrir e consultar dados geoespaciais. Todos os pedidos requerem um Authorization cabeçalho com um token Bearer obtido através da Implementar a autenticação MSAL.
Listar coleções
const API_VERSION = '2025-04-30-preview';
async function listCollections(accessToken, catalogUrl) {
const url = `${catalogUrl}/stac/collections?api-version=${API_VERSION}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to list collections: ${response.statusText}`);
}
const data = await response.json();
return data.collections; // Array of STAC Collection objects
}
Lista de itens numa coleção
const API_VERSION = '2025-04-30-preview';
async function listItems(accessToken, catalogUrl, collectionId, limit = 10) {
const url = `${catalogUrl}/stac/collections/${collectionId}/items?limit=${limit}&api-version=${API_VERSION}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to list items: ${response.statusText}`);
}
const data = await response.json();
return data.features; // Array of STAC Item objects
}
Pesquisa em várias coleções
const API_VERSION = '2025-04-30-preview';
async function searchItems(accessToken, catalogUrl, searchParams) {
const url = `${catalogUrl}/stac/search?api-version=${API_VERSION}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(searchParams),
});
if (!response.ok) {
throw new Error(`Search failed: ${response.statusText}`);
}
return await response.json();
}
// Example usage:
const results = await searchItems(token, catalogUrl, {
collections: ['my-collection'],
bbox: [-122.5, 37.5, -122.0, 38.0], // [west, south, east, north]
datetime: '2024-01-01/2024-12-31',
limit: 20,
});
URLs de mosaico: Construir URLs para visualização de mapas
A API GeoCatalog Tiler serve dados raster como tiles de mapa. Construa URLs de tiles com o seguinte padrão:
Blocos de item único
{catalogUrl}/data/collections/{collectionId}/items/{itemId}/tiles/{z}/{x}/{y}@1x.png
?api-version=2025-04-30-preview
&tileMatrixSetId=WebMercatorQuad
&assets=visual
Função construtora de URL de telhas
const API_VERSION = '2025-04-30-preview';
/**
* Build a tile URL template for a STAC item.
* Returns a URL with {z}/{x}/{y} placeholders for use with map libraries.
*/
function buildTileUrl(catalogUrl, collectionId, itemId, options = {}) {
const { assets = 'visual', colormap, rescale } = options;
const base = `${catalogUrl}/data/collections/${collectionId}/items/${itemId}/tiles/{z}/{x}/{y}@1x.png`;
const params = new URLSearchParams();
params.set('api-version', API_VERSION);
params.set('tileMatrixSetId', 'WebMercatorQuad');
params.set('assets', assets);
if (colormap) params.set('colormap_name', colormap);
if (rescale) params.set('rescale', rescale);
return `${base}?${params.toString()}`;
}
// Example usage:
const tileUrl = buildTileUrl(
'https://mygeocatalog.northcentralus.geocatalog.spatio.azure.com',
'aerial-imagery',
'image-001',
{ assets: 'visual' }
);
Parâmetros chave do tile
| Parâmetro | Obrigatório | Description |
|---|---|---|
api-version |
Yes | Versão API (2025-04-30-preview) |
tileMatrixSetId |
Yes | Utilizar WebMercatorQuad para mapas da web |
assets |
Yes | Nomes de ativos a renderizar (exemplo: visual, image) |
colormap_name |
Não | Colormap nomeado (exemplo: viridis, terrain) |
rescale |
Não | Intervalo de valores para escalonamento (exemplo: 0,255) |
asset_bidx |
Não | Índices de banda (exemplo: image\|1,2,3 para RGB) |
Observação
Para coleções com imagens de quatro bandas (como NAIP com RGB + NIR), use asset_bidx=image|1,2,3 para selecionar apenas as bandas RGB. O tiler não consegue codificar quatro bandas como PNG.
Integração de mapas: Mostrar mosaicos com MapLibre GL
Bibliotecas de mapas como MapLibre GL, Leaflet e OpenLayers podem mostrar blocos raster. O principal desafio é adicionar cabeçalhos de autorização aos pedidos de tiles, uma vez que estas bibliotecas obtêm tiles diretamente.
Exemplo do MapLibre GL
O MapLibre GL oferece uma transformRequest opção para injetar cabeçalhos:
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
// Store the current access token
let currentAccessToken = null;
function initializeMap(containerId, accessToken) {
currentAccessToken = accessToken;
const map = new maplibregl.Map({
container: containerId,
style: {
version: 8,
sources: {
osm: {
type: 'raster',
tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: '© OpenStreetMap contributors',
},
},
layers: [{ id: 'osm', type: 'raster', source: 'osm' }],
},
center: [0, 0],
zoom: 2,
// Add authorization header to tile requests
transformRequest: (url, resourceType) => {
// Only add auth for GeoCatalog tile requests
if (url.includes('geocatalog.spatio.azure.com') && currentAccessToken) {
return {
url,
headers: { 'Authorization': `Bearer ${currentAccessToken}` },
};
}
return { url };
},
});
return map;
}
function addTileLayer(map, tileUrl, bounds) {
// Remove existing layer and source if present
if (map.getLayer('data-layer')) {
map.removeLayer('data-layer');
}
if (map.getSource('data-tiles')) {
map.removeSource('data-tiles');
}
// Add tile source
map.addSource('data-tiles', {
type: 'raster',
tiles: [tileUrl],
tileSize: 256,
minzoom: 10, // Many aerial collections require zoom 10+
maxzoom: 18,
});
// Add tile layer
map.addLayer({
id: 'data-layer',
type: 'raster',
source: 'data-tiles',
});
// Zoom to bounds [west, south, east, north]
if (bounds) {
map.fitBounds([[bounds[0], bounds[1]], [bounds[2], bounds[3]]], { padding: 50 });
}
}
Importante
A função transformRequest é chamada para cada pedido de mosaico. Armazene o token de acesso numa variável que transformRequest possa aceder e atualize-o quando o token for atualizado.
Mosaicos: Exibir imagens de toda a coleção
Para visualizar todos os itens de uma coleção como uma camada uniforme, registe uma pesquisa em mosaico e utilize o ID de pesquisa devolvido.
const API_VERSION = '2025-04-30-preview';
/**
* Register a mosaic search for a collection.
* Returns a search ID that can be used to fetch mosaic tiles.
*/
async function registerMosaic(catalogUrl, collectionId, accessToken) {
const url = `${catalogUrl}/data/mosaic/register?api-version=${API_VERSION}`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
collections: [collectionId],
}),
});
if (!response.ok) {
throw new Error(`Failed to register mosaic: ${response.statusText}`);
}
const data = await response.json();
// Note: API returns 'searchid' (lowercase), not 'searchId'
return data.searchid;
}
/**
* Build a mosaic tile URL template.
*/
function buildMosaicTileUrl(catalogUrl, searchId, collectionId, options = {}) {
const { assets = 'visual' } = options;
const base = `${catalogUrl}/data/mosaic/${searchId}/tiles/{z}/{x}/{y}@1x.png`;
const params = new URLSearchParams();
params.set('api-version', API_VERSION);
params.set('tileMatrixSetId', 'WebMercatorQuad');
params.set('collection', collectionId);
params.set('assets', assets);
return `${base}?${params.toString()}`;
}
Tokens SAS: Descarregar ativos brutos
A API SAS fornece tokens com limite de tempo para descarregar ficheiros brutos de ativos (GeoTIFFs, COGs e outros ficheiros) diretamente do Azure Blob Storage. Use esta opção quando precisar dos ficheiros fonte originais em vez de tiles renderizados.
Importante
Os tokens SAS permitem downloads apenas em aplicações de navegador. Devido às políticas CORS do Azure Blob Storage, os navegadores não conseguem ler dados de blob via JavaScript fetch(). Consulte a secção de limitações do navegador .
Obtenha um token SAS
const API_VERSION = '2025-04-30-preview';
/**
* Get a SAS token for accessing assets in a collection.
* Returns a token string that can be appended to asset URLs.
*/
async function getCollectionSasToken(accessToken, catalogUrl, collectionId) {
const url = `${catalogUrl}/sas/token/${collectionId}?api-version=${API_VERSION}`;
const response = await fetch(url, {
headers: {
'Authorization': `Bearer ${accessToken}`,
},
});
if (!response.ok) {
throw new Error(`Failed to get SAS token: ${response.statusText}`);
}
const data = await response.json();
return data.token; // SAS token string
}
Crie uma URL de download assinada
/**
* Build a signed URL for downloading an asset.
* Appends the SAS token to the asset's href.
*/
function buildSignedAssetUrl(assetHref, sasToken) {
const separator = assetHref.includes('?') ? '&' : '?';
return `${assetHref}${separator}${sasToken}`;
}
// Example usage:
const sasToken = await getCollectionSasToken(accessToken, catalogUrl, 'my-collection');
const assetHref = item.assets['visual'].href;
const signedUrl = buildSignedAssetUrl(assetHref, sasToken);
Desencadear o download de um ficheiro
/**
* Trigger a browser download for an asset file.
* Works by creating a temporary anchor element.
*/
function downloadAsset(signedUrl, filename) {
const link = document.createElement('a');
link.href = signedUrl;
link.download = filename || 'download';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// Example: Download an asset
downloadAsset(signedUrl, 'aerial-image.tif');
Limitações do navegador
Os tokens SAS funcionam de forma diferente nos navegadores em comparação com o código do lado do servidor:
| Caso de uso | Browser | Server-side |
|---|---|---|
| Descarregar ficheiros (utilizador seleciona o link) | ✅ Funciona | ✅ Funciona |
Ler dados de blob através de fetch() |
❌ CORS bloqueado | ✅ Funcionamento |
| Processar píxeis brutos em JavaScript | ❌ Não é possível | ✅ Funciona |
Os downloads do navegador funcionam porque a navegação (clicar em links) contorna o CORS. No entanto, fetch() os pedidos para o Azure Blob Storage são bloqueados porque a conta de armazenamento não inclui a origem da sua aplicação na sua política CORS.
Se a sua aplicação precisar de ler e processar dados brutos de ativos no navegador, implemente um proxy do lado do servidor:
Observação
O código seguinte é um exemplo simplificado para ilustrar o padrão proxy. Para aplicações de produção, o seu endpoint proxy deve autenticar os pedidos (por exemplo, encaminhando o token Bearer do utilizador ou usando autenticação de sessão) e validar que o utilizador está autorizado a aceder aos recursos solicitados.
// ❌ Browser: This fails due to CORS
const response = await fetch(signedUrl);
const data = await response.arrayBuffer(); // Error!
// ✅ Browser: Call your backend instead
const response = await fetch('/api/proxy-asset', {
method: 'POST',
body: JSON.stringify({ collectionId, itemId, assetName })
});
const data = await response.json(); // Works!
O seu backend pode obter o blob usando o token SAS e devolver os resultados processados.
Considerações de desenvolvimento
Suporte CORS
As APIs do GeoCatalog incluem suporte total para CORS com Access-Control-Allow-Origin: *. Aplicações baseadas em navegador podem fazer pedidos diretos ao GeoCatalog a partir de qualquer origem, incluindo http://localhost durante o desenvolvimento. Não é necessário qualquer proxy ou solução alternativa.
A API permite o cabeçalho Authorization nos pedidos CORS, portanto, as chamadas autenticadas fetch() funcionam diretamente a partir do JavaScript do navegador.
Escolher o método certo de acesso a dados
| Método | Navegador fetch() |
Downloads do Navegador | Server-side | Melhor Para |
|---|---|---|---|---|
| Tiler API | ✅ Totalmente suportado | ✅ Sim | ✅ Sim | Visualização de mapas |
| SAS Tokens | ❌ CORS bloqueado | ✅ Sim | ✅ Sim | Downloads de ficheiros em bruto |
API Tiler: Usada para exibir imagens em mapas. Devolve blocos PNG ou WebP renderizados com suporte total para CORS. Veja URLs de Tile e integração de mapas.
Tokens SAS: Usados para descarregar ficheiros fonte originais (GeoTIFFs, COGs). Os downloads do navegador funcionam, mas
fetch()são bloqueados pelas políticas CORS do Azure Blob Storage. Consulte os tokens SAS para detalhes e soluções alternativas.
Atualização de token
Os tokens de acesso expiram, normalmente após uma hora. A sua candidatura deve:
- Trate dos erros 401 adquirindo um novo token.
- Use a aquisição silenciosa de tokens da MSAL, que atualiza automaticamente os tokens expirados.
- Atualize a referência do token utilizada pelo seu mapa no
transformRequest.
Tratamento de erros
Lidar com cenários de erro comuns:
| Estado HTTP | Motivo | Solução |
|---|---|---|
| 401 | Token expirado ou inválido | Atualizar o token de acesso |
| 404 | Item ou coleção não encontrados | Verificar se os IDs existem |
| 424 | Tile fora da extensão de dados | Esperado - manuseio com elegância |
Solução de problemas
| Erro | Motivo | Solução |
|---|---|---|
| "AADSTS50011: URL de resposta incompatível" | O URI de redirecionamento no código não coincide com o registo do Microsoft Entra ID | Adicione o seu URL de desenvolvimento (por exemplo, http://localhost:3000) como um URI de redirecionamento SPA no registo da sua aplicação |
| Erro de âmbito inválido | Usar URL do GeoCatálogo em vez do âmbito da API | Utilize https://geocatalog.spatio.azure.com/.default como escopo |
| 401 Não autorizado em pedidos de blocos de interface | Biblioteca de mapas que não inclui cabeçalhos de autenticação | Use transformRequest (MapLibre) para adicionar o token do Portador; certifique-se de que o token está atualizado |
| Os tiles não se alinham com o basemap | Conjunto de blocos de matriz incorreto | Utilização tileMatrixSetId=WebMercatorQuad para projeção Web Mercator (EPSG:3857) |
| "Não consegui decifrar a imagem" | Nome de ativo errado, imagens multibanda ou extensão externa dos dados | Verifique item_assets para nomes válidos; utilize asset_bidx=image\|1,2,3 para RGB; é esperado que 404/424 esteja fora da cobertura. |