Electron中用@nodert-win10创建的Win10 Toast无法加载网络图片怎么办?
I'm trying to display web images in Windows 10 Toast notifications from my Electron app, but it's failing—only local images load correctly. Here's my current code:
const { XmlDocument } = require('@nodert-win10/windows.data.xml.dom'); const { ToastNotification, ToastNotificationManager } = require('@nodert-win10/windows.ui.notifications'); const path = require('path'); const localImage = path.join(__dirname, 'image.jpg'); const webImage = 'http://picsum.photos/360/202?image=11'; const template = ` <toast launch="app-defined-string"> <visual> <binding template="ToastGeneric"> <image id="1" placement="appLogoOverride" hint-crop="circle" src="${localImage}"/> <image id="2" placement="hero" src="${webImage}"/> </binding> </visual> </toast> `; const xml = new XmlDocument(); xml.loadXml(template); const toast = new ToastNotification(xml); const notifier = ToastNotificationManager.createToastNotifier(appId); notifier.show(toast);
Is there any way to get Windows 10 Toast notifications from an Electron app to support loading web images?
Got it, the core issue here is that Windows Toast notifications have a strict security restriction—they can’t load remote images directly. They only accept local file paths or assets packaged with your application. The workaround is straightforward: download the web image to a temporary local directory first, then reference that local path in your toast template.
Here’s how to adjust your code to make this work:
Use Node.js built-in modules for downloading and file handling: We’ll use
https(orhttpfor non-HTTPS URLs),fs, andosto handle the download, file system operations, and temp directory management. No extra libraries are required if you stick to these.Modified working code:
const { XmlDocument } = require('@nodert-win10/windows.data.xml.dom'); const { ToastNotification, ToastNotificationManager } = require('@nodert-win10/windows.ui.notifications'); const path = require('path'); const fs = require('fs'); const https = require('https'); // Swap with 'http' if your image uses HTTP const os = require('os'); const localImage = path.join(__dirname, 'image.jpg'); const webImageUrl = 'http://picsum.photos/360/202?image=11'; const appId = 'your-app-unique-id'; // Don't forget to set this correctly! // Helper function to download a web image to the system temp folder function downloadWebImage(url, callback) { // Create a unique temp file path to avoid conflicts const tempDir = os.tmpdir(); const tempFilePath = path.join(tempDir, `toast-hero-image-${Date.now()}.jpg`); const fileStream = fs.createWriteStream(tempFilePath); https.get(url, (response) => { response.pipe(fileStream); fileStream.on('finish', () => { fileStream.close(() => callback(null, tempFilePath)); }); }).on('error', (err) => { // Clean up the partial temp file if download fails fs.unlink(tempFilePath, () => {}); callback(err); }); } // Download the image first, then show the toast downloadWebImage(webImageUrl, (err, tempImagePath) => { if (err) { console.error('Failed to download web image:', err); return; } const toastTemplate = ` <toast launch="app-defined-string"> <visual> <binding template="ToastGeneric"> <image id="1" placement="appLogoOverride" hint-crop="circle" src="${localImage}"/> <image id="2" placement="hero" src="${tempImagePath}"/> </binding> </visual> </toast> `; const xmlDoc = new XmlDocument(); xmlDoc.loadXml(toastTemplate); const toast = new ToastNotification(xmlDoc); // Optional: Clean up the temp image after the toast is dismissed toast.addEventListener('dismissed', () => { fs.unlink(tempImagePath, (cleanupErr) => { if (cleanupErr) console.error('Failed to delete temp image:', cleanupErr); }); }); const notifier = ToastNotificationManager.createToastNotifier(appId); notifier.show(toast); });
Important Tips:
- Temp File Cleanup: Adding a listener for the toast’s
dismissedevent ensures we delete the temp image after the user interacts with or ignores the toast, so you don’t leave unnecessary files cluttering the system. - App ID: Make sure your
appIdis a unique identifier for your Electron app—Windows requires this to properly manage toast notifications. - Protocol Handling: If your image URL uses HTTP instead of HTTPS, replace the
httpsmodule withhttpin the require statement and usehttp.get()instead. - Error Handling: The code includes basic error handling for download failures, but you can expand this to show a fallback toast without the image if needed.
This approach works because we’re converting the remote image into a local file that the Windows Toast system can access, getting around the remote resource security block.
内容的提问来源于stack exchange,提问作者olegshilov

