Skip to content

Commit 6b854a2

Browse files
authored
fix: guard large GeoTIFF COG conversions (#1925)
* fix: guard large GeoTIFF COG conversions * Address Claude review feedback - explain the browser conversion size limit directly in every locale - avoid recalculating the decoded raster sample count * Address Claude review feedback - reject unreadable metadata before applying the size label - co-locate and test the warning and hard conversion thresholds * Address Claude review feedback - enforce the sample limit inside the shared browser converter - export shared thresholds for localized Add Raster preflight
1 parent b60ae69 commit 6b854a2

23 files changed

Lines changed: 88 additions & 12 deletions

File tree

apps/geolibre-desktop/src/components/layout/DesktopShell.tsx

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,14 @@ import {
4343
TIME_SLIDER_PLUGIN_ID,
4444
VIEWER_BLOCKED_PLUGIN_IDS,
4545
} from "@geolibre/plugins";
46-
import { convertGeoTiffToCog, isTiff, readGeoTiffInfo } from "@geolibre/processing";
46+
import {
47+
convertGeoTiffToCog,
48+
exceedsBrowserCogConversionLimit,
49+
geoTiffSampleCount,
50+
isTiff,
51+
LARGE_BROWSER_COG_CONVERSION_SAMPLES,
52+
readGeoTiffInfo,
53+
} from "@geolibre/processing";
4754
import {
4855
type CSSProperties,
4956
type DragEvent,
@@ -187,14 +194,6 @@ import type { ProjectUrlLoadState } from "../../hooks/useProjectUrlLoader";
187194
* `window.confirm` (see the handlers below): a `false` return aborts that one
188195
* file's load without affecting the rest of a multi-file drop.
189196
*/
190-
/**
191-
* Sample count (width × height × bands) above which in-browser COG conversion
192-
* gets an extra "this may be slow / memory-intensive" confirmation. The
193-
* converter reads the whole raster into memory as f64, so ~40M samples is
194-
* roughly where the transient allocation starts to be felt.
195-
*/
196-
const LARGE_RASTER_SAMPLE_LIMIT = 40_000_000;
197-
198197
function confirmLargeVectorDataset({ name, featureCount }: LargeVectorDataset) {
199198
return window.confirm(
200199
i18n.t("toolbar.item.largeVectorDesc", {
@@ -1141,13 +1140,21 @@ export function DesktopShell({
11411140
window.alert(t("raster.rasterNotGeotiff", { name }));
11421141
return;
11431142
}
1143+
const info = await readGeoTiffInfo(bytes);
1144+
if (!info.ok) throw new Error("Not a readable GeoTIFF.");
1145+
const samples = geoTiffSampleCount(info);
1146+
if (exceedsBrowserCogConversionLimit(samples)) {
1147+
console.warn(
1148+
`[GeoLibre] Skipping in-browser COG conversion for "${name}": ${samples.toLocaleString()} decoded samples exceed the safe memory limit.`,
1149+
);
1150+
window.alert(t("raster.cogConvertTooLarge", { name }));
1151+
return;
1152+
}
11441153
if (!bytesAreRemote) {
11451154
// Local file: pick the prompt by size now that the header is cheap to
11461155
// read, then confirm once. (A remote source already confirmed above.)
1147-
const info = await readGeoTiffInfo(bytes);
1148-
const samples = info.width * info.height * Math.max(info.bands, 1);
11491156
const message =
1150-
samples > LARGE_RASTER_SAMPLE_LIMIT
1157+
samples > LARGE_BROWSER_COG_CONVERSION_SAMPLES
11511158
? t("raster.cogConvertLargeConfirm", {
11521159
name,
11531160
width: info.width,

apps/geolibre-desktop/src/i18n/locales/ar.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5601,6 +5601,7 @@
56015601
"cogConvertConfirm": "\"{{name}}\" هو ملف GeoTIFF عادي (شرائطي) لا يمكن عرضه مباشرة. هل تريد تحويله الآن إلى Cloud-Optimized GeoTIFF وتحميل الناتج؟",
56025602
"cogConvertRemoteConfirm": "\"{{name}}\" هو ملف GeoTIFF عادي (شرائطي) لا يمكن عرضه مباشرة. يتطلب عرضه تنزيل الملف كاملًا وتحويله إلى Cloud-Optimized GeoTIFF في المتصفح، وقد يكون ذلك بطيئًا ومستهلكًا للذاكرة مع الملفات الكبيرة. هل تريد المتابعة؟",
56035603
"cogConvertLargeConfirm": "\"{{name}}\" هو ملف GeoTIFF كبير بأبعاد {{width}}×{{height}} وليس Cloud-Optimized GeoTIFF. قد يكون تحويله في المتصفح بطيئًا ومستهلكًا للذاكرة. هل تريد تحويله وتحميله على أي حال؟",
5604+
"cogConvertTooLarge": "ملف \"{{name}}\" كبير جدًا بحيث لا يمكن تحويله بأمان في المتصفح. حوّله إلى Cloud-Optimized GeoTIFF باستخدام gdal_translate أو rio cogeo، ثم حمّل الناتج.",
56045605
"cogConvertFailed": "تعذر تحويل \"{{name}}\" إلى Cloud-Optimized GeoTIFF. جرّب تحويله باستخدام gdal_translate أو rio cogeo، ثم حمّل الناتج.",
56055606
"rasterDownloadFailed": "تعذر تنزيل \"{{name}}\". قد يكون الخادم بطيئًا أو يتعذر الوصول إليه أو يحظر الطلبات عابرة المصادر، أو قد يكون الملف أكبر من أن يُحفظ في الذاكرة. تحقق من عنوان URL وحاول مرة أخرى.",
56065607
"rasterNotGeotiff": "لم يُرجع \"{{name}}\" ملف GeoTIFF. ربما أرسل الخادم صفحة خطأ أو صفحة تسجيل دخول بدلًا منه. تحقق من عنوان URL وحاول مرة أخرى."

apps/geolibre-desktop/src/i18n/locales/de.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,7 @@
53025302
"cogConvertConfirm": "\"{{name}}\" ist ein einfaches (gestreiftes) GeoTIFF, das nicht direkt angezeigt werden kann. Jetzt in ein Cloud-Optimized GeoTIFF konvertieren und dieses laden?",
53035303
"cogConvertRemoteConfirm": "\"{{name}}\" ist ein einfaches (gestreiftes) GeoTIFF, das nicht direkt angezeigt werden kann. Es anzuzeigen bedeutet, die vollständige Datei herunterzuladen und im Browser in ein Cloud-Optimized GeoTIFF zu konvertieren, was bei großen Dateien langsam und speicherintensiv sein kann. Fortfahren?",
53045304
"cogConvertLargeConfirm": "\"{{name}}\" ist ein großes {{width}}×{{height}}-GeoTIFF, das kein Cloud-Optimized GeoTIFF ist. Die Konvertierung im Browser kann langsam und speicherintensiv sein. Trotzdem konvertieren und laden?",
5305+
"cogConvertTooLarge": "„{{name}}“ ist zu groß, um sicher im Browser konvertiert zu werden. Konvertieren Sie die Datei mit gdal_translate oder rio cogeo in ein Cloud-Optimized GeoTIFF und laden Sie anschließend das Ergebnis.",
53055306
"cogConvertFailed": "\"{{name}}\" konnte nicht in ein Cloud-Optimized GeoTIFF konvertiert werden. Versuchen Sie, es mit gdal_translate oder rio cogeo zu konvertieren, und laden Sie dann das Ergebnis.",
53065307
"rasterDownloadFailed": "\"{{name}}\" konnte nicht heruntergeladen werden. Der Server ist möglicherweise langsam, nicht erreichbar oder blockiert Cross-Origin-Anfragen, oder die Datei ist zu groß, um im Speicher gehalten zu werden. Überprüfen Sie die URL und versuchen Sie es erneut.",
53075308
"rasterNotGeotiff": "\"{{name}}\" hat kein GeoTIFF zurückgegeben. Der Server hat möglicherweise stattdessen eine Fehler- oder Anmeldeseite gesendet. Überprüfen Sie die URL und versuchen Sie es erneut."

apps/geolibre-desktop/src/i18n/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5313,6 +5313,7 @@
53135313
"cogConvertConfirm": "\"{{name}}\" is a plain (striped) GeoTIFF, which cannot be displayed directly. Convert it to a Cloud-Optimized GeoTIFF now and load that?",
53145314
"cogConvertRemoteConfirm": "\"{{name}}\" is a plain (striped) GeoTIFF, which cannot be displayed directly. Displaying it means downloading the full file and converting it to a Cloud-Optimized GeoTIFF in the browser, which can be slow and memory-intensive for large files. Proceed?",
53155315
"cogConvertLargeConfirm": "\"{{name}}\" is a large {{width}}×{{height}} GeoTIFF that is not a Cloud-Optimized GeoTIFF. Converting it in the browser may be slow and memory-intensive. Convert and load it anyway?",
5316+
"cogConvertTooLarge": "\"{{name}}\" is too large to convert safely in the browser. Convert it to a Cloud-Optimized GeoTIFF with gdal_translate or rio cogeo, then load the result.",
53165317
"cogConvertFailed": "Could not convert \"{{name}}\" to a Cloud-Optimized GeoTIFF. Try converting it with gdal_translate or rio cogeo, then load the result.",
53175318
"rasterDownloadFailed": "Could not download \"{{name}}\". The server may be slow, unreachable, or blocking cross-origin requests, or the file may be too large to hold in memory. Check the URL and try again.",
53185319
"rasterNotGeotiff": "\"{{name}}\" did not return a GeoTIFF. The server may have sent an error or login page instead. Check the URL and try again."

apps/geolibre-desktop/src/i18n/locales/es.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,7 @@
53025302
"cogConvertConfirm": "«{{name}}» es un GeoTIFF simple (por franjas), que no se puede mostrar directamente. ¿Convertirlo ahora a un GeoTIFF optimizado para la nube y cargar ese?",
53035303
"cogConvertRemoteConfirm": "«{{name}}» es un GeoTIFF simple (por franjas), que no se puede mostrar directamente. Mostrarlo implica descargar el archivo completo y convertirlo a un GeoTIFF optimizado para la nube en el navegador, lo que puede ser lento y usar mucha memoria en archivos grandes. ¿Continuar?",
53045304
"cogConvertLargeConfirm": "«{{name}}» es un GeoTIFF grande de {{width}}×{{height}} que no está optimizado para la nube. Convertirlo en el navegador puede ser lento y usar mucha memoria. ¿Convertirlo y cargarlo de todos modos?",
5305+
"cogConvertTooLarge": "«{{name}}» es demasiado grande para convertirlo de forma segura en el navegador. Conviértalo en un GeoTIFF optimizado para la nube con gdal_translate o rio cogeo y cargue el resultado.",
53055306
"cogConvertFailed": "No se pudo convertir «{{name}}» a un GeoTIFF optimizado para la nube. Intente convertirlo con gdal_translate o rio cogeo y luego cargue el resultado.",
53065307
"rasterDownloadFailed": "No se pudo descargar «{{name}}». Es posible que el servidor esté lento, no esté disponible o bloquee solicitudes entre orígenes, o que el archivo sea demasiado grande para mantenerlo en memoria. Compruebe la URL e inténtelo de nuevo.",
53075308
"rasterNotGeotiff": "«{{name}}» no devolvió un GeoTIFF. Es posible que el servidor haya enviado una página de error o de inicio de sesión en su lugar. Compruebe la URL e inténtelo de nuevo."

apps/geolibre-desktop/src/i18n/locales/fa.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,7 @@
53025302
"cogConvertConfirm": "«{{name}}» یک GeoTIFF ساده (نواری) است که مستقیم نمایش‌پذیر نیست. اکنون به یک GeoTIFF بهینه‌شده برای ابر تبدیل و همان بارگیری شود؟",
53035303
"cogConvertRemoteConfirm": "«{{name}}» یک GeoTIFF ساده (نواری) است که مستقیم نمایش‌پذیر نیست. نمایش آن یعنی دانلود کل فایل و تبدیلش به یک GeoTIFF بهینه‌شده برای ابر در مرورگر، که برای فایل‌های بزرگ می‌تواند کند و پرمصرف باشد. ادامه می‌دهید؟",
53045304
"cogConvertLargeConfirm": "«{{name}}» یک GeoTIFF بزرگ {{width}}×{{height}} است که بهینه‌شده برای ابر نیست. تبدیل آن در مرورگر ممکن است کند و پرمصرف باشد. به‌هر‌حال تبدیل و بارگیری شود؟",
5305+
"cogConvertTooLarge": "«{{name}}» برای تبدیل ایمن در مرورگر بیش از حد بزرگ است. آن را با gdal_translate یا rio cogeo به یک Cloud-Optimized GeoTIFF تبدیل کنید، سپس نتیجه را بارگیری کنید.",
53055306
"cogConvertFailed": "تبدیل «{{name}}» به یک GeoTIFF بهینه‌شده برای ابر با شکست مواجه شد. آن را با gdal_translate یا rio cogeo تبدیل کنید، سپس نتیجه را بارگیری کنید.",
53065307
"rasterDownloadFailed": "دانلود «{{name}}» با شکست مواجه شد. ممکن است سرور کند یا خارج از دسترس باشد یا درخواست‌های میان‌مبدأ را مسدود کند، یا فایل برای نگه داشتن در حافظه بسیار بزرگ باشد. نشانی را بررسی کنید و دوباره تلاش کنید.",
53075308
"rasterNotGeotiff": "«{{name}}» یک GeoTIFF برنگرداند. ممکن است سرور به‌جای آن صفحهٔ خطا یا ورود فرستاده باشد. نشانی را بررسی کنید و دوباره تلاش کنید."

apps/geolibre-desktop/src/i18n/locales/fr.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,7 @@
53025302
"cogConvertConfirm": "« {{name}} » est un GeoTIFF simple (par bandes), qui ne peut pas être affiché directement. Le convertir maintenant en GeoTIFF Cloud-Optimized et le charger ?",
53035303
"cogConvertRemoteConfirm": "« {{name}} » est un GeoTIFF simple (par bandes), qui ne peut pas être affiché directement. L'afficher implique de télécharger le fichier complet et de le convertir en GeoTIFF Cloud-Optimized dans le navigateur, ce qui peut être lent et gourmand en mémoire pour les fichiers volumineux. Continuer ?",
53045304
"cogConvertLargeConfirm": "« {{name}} » est un grand GeoTIFF {{width}}×{{height}} qui n'est pas un GeoTIFF Cloud-Optimized. Le convertir dans le navigateur peut être lent et gourmand en mémoire. Le convertir et le charger quand même ?",
5305+
"cogConvertTooLarge": "« {{name}} » est trop volumineux pour être converti en toute sécurité dans le navigateur. Convertissez-le en GeoTIFF Cloud-Optimized avec gdal_translate ou rio cogeo, puis chargez le résultat.",
53055306
"cogConvertFailed": "Impossible de convertir « {{name}} » en GeoTIFF Cloud-Optimized. Essayez de le convertir avec gdal_translate ou rio cogeo, puis chargez le résultat.",
53065307
"rasterDownloadFailed": "Impossible de télécharger « {{name}} ». Le serveur est peut-être lent, inaccessible ou bloque les requêtes cross-origin, ou le fichier est peut-être trop volumineux pour tenir en mémoire. Vérifiez l'URL et réessayez.",
53075308
"rasterNotGeotiff": "« {{name}} » n'a pas renvoyé de GeoTIFF. Le serveur a peut-être envoyé une erreur ou une page de connexion à la place. Vérifiez l'URL et réessayez."

apps/geolibre-desktop/src/i18n/locales/hi.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,7 @@
53025302
"cogConvertConfirm": "\"{{name}}\" एक सामान्य (striped) GeoTIFF है, जिसे सीधे प्रदर्शित नहीं किया जा सकता। क्या इसे अभी Cloud-Optimized GeoTIFF में बदलकर लोड करें?",
53035303
"cogConvertRemoteConfirm": "\"{{name}}\" एक सामान्य (striped) GeoTIFF है, जिसे सीधे प्रदर्शित नहीं किया जा सकता। इसे प्रदर्शित करने के लिए पूरी फ़ाइल डाउनलोड करके ब्राउज़र में उसे Cloud-Optimized GeoTIFF में बदलना होगा, जो बड़ी फ़ाइलों के लिए धीमा और मेमोरी-गहन हो सकता है। जारी रखें?",
53045304
"cogConvertLargeConfirm": "\"{{name}}\" एक बड़ी {{width}}×{{height}} GeoTIFF है जो Cloud-Optimized GeoTIFF नहीं है। इसे ब्राउज़र में बदलना धीमा और मेमोरी-गहन हो सकता है। फिर भी बदलकर लोड करें?",
5305+
"cogConvertTooLarge": "\"{{name}}\" ब्राउज़र में सुरक्षित रूप से बदलने के लिए बहुत बड़ा है। इसे gdal_translate या rio cogeo से Cloud-Optimized GeoTIFF में बदलें, फिर परिणाम लोड करें।",
53055306
"cogConvertFailed": "\"{{name}}\" को Cloud-Optimized GeoTIFF में नहीं बदला जा सका। gdal_translate या rio cogeo से बदलने का प्रयास करें, फिर परिणाम लोड करें।",
53065307
"rasterDownloadFailed": "\"{{name}}\" डाउनलोड नहीं की जा सकी। सर्वर धीमा, अनुपलब्ध, या क्रॉस-ओरिजिन रिक्वेस्ट ब्लॉक कर रहा हो सकता है, या फ़ाइल मेमोरी में रखने के लिए बहुत बड़ी हो सकती है। URL जांचें और पुनः प्रयास करें।",
53075308
"rasterNotGeotiff": "\"{{name}}\" ने GeoTIFF नहीं लौटाई। सर्वर ने इसके बजाय एक त्रुटि या लॉगिन पेज भेजा हो सकता है। URL जांचें और पुनः प्रयास करें।"

apps/geolibre-desktop/src/i18n/locales/id.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5227,6 +5227,7 @@
52275227
"cogConvertConfirm": "\"{{name}}\" adalah GeoTIFF biasa (bergaris), yang tidak dapat ditampilkan langsung. Konversi ke Cloud-Optimized GeoTIFF sekarang dan muat itu?",
52285228
"cogConvertRemoteConfirm": "\"{{name}}\" adalah GeoTIFF biasa (bergaris), yang tidak dapat ditampilkan langsung. Menampilkannya berarti mengunduh seluruh file dan mengonversinya menjadi Cloud-Optimized GeoTIFF di browser, yang bisa lambat dan menguras memori untuk file besar. Lanjutkan?",
52295229
"cogConvertLargeConfirm": "\"{{name}}\" adalah GeoTIFF {{width}}×{{height}} besar yang bukan Cloud-Optimized GeoTIFF. Mengonversinya di browser mungkin lambat dan menguras memori. Konversi dan muat saja?",
5230+
"cogConvertTooLarge": "\"{{name}}\" terlalu besar untuk dikonversi dengan aman di browser. Konversikan menjadi Cloud-Optimized GeoTIFF dengan gdal_translate atau rio cogeo, lalu muat hasilnya.",
52305231
"cogConvertFailed": "Tidak dapat mengonversi \"{{name}}\" menjadi Cloud-Optimized GeoTIFF. Coba konversi dengan gdal_translate atau rio cogeo, lalu muat hasilnya.",
52315232
"rasterDownloadFailed": "Tidak dapat mengunduh \"{{name}}\". Server mungkin lambat, tidak dapat dijangkau, atau memblokir permintaan lintas asal, atau file mungkin terlalu besar untuk disimpan dalam memori. Periksa URL dan coba lagi.",
52325233
"rasterNotGeotiff": "\"{{name}}\" tidak mengembalikan GeoTIFF. Server mungkin mengirim halaman kesalahan atau login sebagai gantinya. Periksa URL dan coba lagi."

apps/geolibre-desktop/src/i18n/locales/it.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5302,6 +5302,7 @@
53025302
"cogConvertConfirm": "\"{{name}}\" è un GeoTIFF semplice (a strisce), che non può essere visualizzato direttamente. Convertirlo ora in un Cloud-Optimized GeoTIFF e caricare quello?",
53035303
"cogConvertRemoteConfirm": "\"{{name}}\" è un GeoTIFF semplice (a strisce), che non può essere visualizzato direttamente. Visualizzarlo implica scaricare il file completo e convertirlo in un Cloud-Optimized GeoTIFF nel browser, un'operazione che può essere lenta e richiedere molta memoria per i file di grandi dimensioni. Procedere?",
53045304
"cogConvertLargeConfirm": "\"{{name}}\" è un GeoTIFF di grandi dimensioni ({{width}}×{{height}}) che non è un Cloud-Optimized GeoTIFF. La conversione nel browser potrebbe essere lenta e richiedere molta memoria. Convertirlo e caricarlo comunque?",
5305+
"cogConvertTooLarge": "«{{name}}» è troppo grande per essere convertito in modo sicuro nel browser. Convertilo in un GeoTIFF Cloud-Optimized con gdal_translate o rio cogeo, quindi carica il risultato.",
53055306
"cogConvertFailed": "Impossibile convertire \"{{name}}\" in un Cloud-Optimized GeoTIFF. Prova a convertirlo con gdal_translate o rio cogeo, quindi carica il risultato.",
53065307
"rasterDownloadFailed": "Impossibile scaricare \"{{name}}\". Il server potrebbe essere lento, irraggiungibile o potrebbe bloccare le richieste cross-origin, oppure il file potrebbe essere troppo grande per essere mantenuto in memoria. Controlla l'URL e riprova.",
53075308
"rasterNotGeotiff": "\"{{name}}\" non ha restituito un GeoTIFF. Il server potrebbe aver inviato una pagina di errore o di accesso al suo posto. Controlla l'URL e riprova."

0 commit comments

Comments
 (0)