<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: KmlNode  - WriteToAsync() - doesnt included referenced image files in .NET Maps SDK Questions</title>
    <link>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1022041#M9731</link>
    <description>&lt;P&gt;Hello Justin!&lt;/P&gt;&lt;P&gt;I'm guessing that the GroundOverlay references a remote file (i.e. GroundOverlay/Icon/href is an HTTP/HTTPS URL rather than a file path).&amp;nbsp; This would explain why the TIFF is not being saved in the KMZ archive.&amp;nbsp; When a KMLNode is saved, only the URLs to remote files are saved -- the remote content does not downloaded and does not get zipped up. You can find more details about the saving process in the&amp;nbsp;&lt;A href="https://developers.arcgis.com/net/uwp/api-reference/html/M_Esri_ArcGISRuntime_Ogc_KmlNode_SaveAsAsync.htm" target="_self"&gt;remarks of KmlNode.SaveAsAsync(...) method&lt;/A&gt;.&lt;/P&gt;&lt;P&gt;As a workaround, you can edit the KMLGroundOverlay before saving. First get its Icon, then download the Uri to a temporary file, create a new KMLIcon with a path to the temporary file, and finally replace the overlay Icon. Here's an example of how you could do it:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;// Ensures that GroundOverlays's image will be saved as an embedded file
private async Task DownloadOverlayImageAsync(KmlGroundOverlay original)
{
    var icon = original.Icon;
    if (icon == null || icon.Uri == null || !icon.Uri.IsAbsoluteUri)
        return; // Skip invalid and already-local overlays

    // Create a temporary file to save to.
    // Filename is based on the URL, with any invalid characters replaced by "_".
    var imageFileName = Regex.Replace(icon.Uri.LocalPath, @"[^a-zA-Z0-9_\-\.]", "_");
    var temp = ApplicationData.Current.TemporaryFolder;
    var tempSubfolder = await temp.CreateFolderAsync("KmlGroundOverlayDownloads", CreationCollisionOption.OpenIfExists);
    var tempFile = await tempSubfolder.CreateFileAsync(imageFileName, CreationCollisionOption.GenerateUniqueName);

    // Download using Runtime's HTTP handler (to integrate with AuthenticationManager)
    var client = new System.Net.Http.HttpClient(new ArcGISHttpClientHandler());
    using (var stream = await client.GetStreamAsync(icon.Uri))
    {
        using (var fileStream = await tempFile.OpenStreamForWriteAsync())
        {
            await stream.CopyToAsync(fileStream);
        }
    }

    // Replace existing remote-URL icon with new local-URL icon
    var newIcon = new KmlIcon(new Uri(tempFile.Path));
    original.Icon = newIcon;
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Mon, 01 Feb 2021 10:39:31 GMT</pubDate>
    <dc:creator>MatveiStefarov</dc:creator>
    <dc:date>2021-02-01T10:39:31Z</dc:date>
    <item>
      <title>KmlNode  - WriteToAsync() - doesnt included referenced image files</title>
      <link>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1021564#M9729</link>
      <description>&lt;P&gt;I am reading in a KmlGroundOverlay that references a tiff file.&amp;nbsp;&lt;/P&gt;&lt;P&gt;I write the KmlGroundOverlay to a a Stream.&lt;/P&gt;&lt;P&gt;I save the Stream to a file.&lt;/P&gt;&lt;P&gt;Everything works as expected except the referenced tiff file is not included in the KMZ.&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Is this because I'm importing into the incorrect place when i first read the file?&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;My&amp;nbsp; KmlGroundOverlays are displayed as excepted over my basemaps in my app.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;private async Task LoadAndSaveKmz(StorageFile file, StorageFolder exportFolder)
{
  var localFile = await 
      ApplicationData.Current.TemporaryFolder.CreateFileAsync(
      file.Name, Windows.Storage.CreationCollisionOption.ReplaceExisting);
  await file.CopyAndReplaceAsync(localFile);
  source = new Uri(localFile.Path);
  KmlLayer layer = new KmlLayer(source);
  await layer.LoadAsync();
  //get access to kml node (omitting that code here)
  KmlNode node = GetNodeFromLayer(layer);
  string filename = "node.kmz";
  StorageFile file = await exportFolder.CreateFileAsync(filename, 
      CreationCollisionOption.ReplaceExisting);
  using (Stream stream = await file.OpenStreamForWriteAsync())
  {
     await node.WriteToAsync(stream);
  }
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 29 Jan 2021 16:33:10 GMT</pubDate>
      <guid>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1021564#M9729</guid>
      <dc:creator>justinfernandes</dc:creator>
      <dc:date>2021-01-29T16:33:10Z</dc:date>
    </item>
    <item>
      <title>Re: KmlNode  - WriteToAsync() - doesnt included referenced image files</title>
      <link>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1022041#M9731</link>
      <description>&lt;P&gt;Hello Justin!&lt;/P&gt;&lt;P&gt;I'm guessing that the GroundOverlay references a remote file (i.e. GroundOverlay/Icon/href is an HTTP/HTTPS URL rather than a file path).&amp;nbsp; This would explain why the TIFF is not being saved in the KMZ archive.&amp;nbsp; When a KMLNode is saved, only the URLs to remote files are saved -- the remote content does not downloaded and does not get zipped up. You can find more details about the saving process in the&amp;nbsp;&lt;A href="https://developers.arcgis.com/net/uwp/api-reference/html/M_Esri_ArcGISRuntime_Ogc_KmlNode_SaveAsAsync.htm" target="_self"&gt;remarks of KmlNode.SaveAsAsync(...) method&lt;/A&gt;.&lt;/P&gt;&lt;P&gt;As a workaround, you can edit the KMLGroundOverlay before saving. First get its Icon, then download the Uri to a temporary file, create a new KMLIcon with a path to the temporary file, and finally replace the overlay Icon. Here's an example of how you could do it:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;// Ensures that GroundOverlays's image will be saved as an embedded file
private async Task DownloadOverlayImageAsync(KmlGroundOverlay original)
{
    var icon = original.Icon;
    if (icon == null || icon.Uri == null || !icon.Uri.IsAbsoluteUri)
        return; // Skip invalid and already-local overlays

    // Create a temporary file to save to.
    // Filename is based on the URL, with any invalid characters replaced by "_".
    var imageFileName = Regex.Replace(icon.Uri.LocalPath, @"[^a-zA-Z0-9_\-\.]", "_");
    var temp = ApplicationData.Current.TemporaryFolder;
    var tempSubfolder = await temp.CreateFolderAsync("KmlGroundOverlayDownloads", CreationCollisionOption.OpenIfExists);
    var tempFile = await tempSubfolder.CreateFileAsync(imageFileName, CreationCollisionOption.GenerateUniqueName);

    // Download using Runtime's HTTP handler (to integrate with AuthenticationManager)
    var client = new System.Net.Http.HttpClient(new ArcGISHttpClientHandler());
    using (var stream = await client.GetStreamAsync(icon.Uri))
    {
        using (var fileStream = await tempFile.OpenStreamForWriteAsync())
        {
            await stream.CopyToAsync(fileStream);
        }
    }

    // Replace existing remote-URL icon with new local-URL icon
    var newIcon = new KmlIcon(new Uri(tempFile.Path));
    original.Icon = newIcon;
}&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Mon, 01 Feb 2021 10:39:31 GMT</pubDate>
      <guid>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1022041#M9731</guid>
      <dc:creator>MatveiStefarov</dc:creator>
      <dc:date>2021-02-01T10:39:31Z</dc:date>
    </item>
    <item>
      <title>Re: KmlNode  - WriteToAsync() - doesnt included referenced image files</title>
      <link>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1022229#M9740</link>
      <description>&lt;P&gt;Thanks for the detailed response! Lots of good stuff in there.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Unfortunately that is not my case.&amp;nbsp; The image file is within a KMZ that was initially loaded by my App.&amp;nbsp; The entire KMZ is copied to my Temporary Folder within my apps "sandbox".&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I suppose i could manually unzip that kmz and move that file to somewhere in my local sandbox, and then specify a relative to path to that location.&amp;nbsp;&amp;nbsp;&lt;/P&gt;&lt;P&gt;So my main question becomes:&amp;nbsp; How should i define the relative path within my new kml?&amp;nbsp; where should the path be relative to such that WriteToSync() works successfully?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Also, is it possible to specify a path such that it finds a a file within another kmz (to prevent need for unzipping).&lt;/P&gt;&lt;P&gt;thanks!&lt;/P&gt;</description>
      <pubDate>Mon, 01 Feb 2021 18:45:56 GMT</pubDate>
      <guid>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1022229#M9740</guid>
      <dc:creator>justinfernandes</dc:creator>
      <dc:date>2021-02-01T18:45:56Z</dc:date>
    </item>
    <item>
      <title>Re: KmlNode  - WriteToAsync() - doesnt included referenced image files</title>
      <link>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1022313#M9741</link>
      <description>&lt;P&gt;&lt;a href="https://community.esri.com/t5/user/viewprofilepage/user-id/72688"&gt;@justinfernandes&lt;/a&gt;&amp;nbsp; One more thing to check - which version are you using? If it's not v100.10, can you update to 100.10 and retest?&lt;/P&gt;</description>
      <pubDate>Mon, 01 Feb 2021 21:08:50 GMT</pubDate>
      <guid>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1022313#M9741</guid>
      <dc:creator>MichaelBranscomb</dc:creator>
      <dc:date>2021-02-01T21:08:50Z</dc:date>
    </item>
    <item>
      <title>Re: KmlNode  - WriteToAsync() - doesnt included referenced image files</title>
      <link>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1053916#M10055</link>
      <description>&lt;P&gt;changing versions did not help.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;but i eventually solved the problem by reading the image file into a WriteableBitmap, writing that bitmap to my ApplicatoinData.Current.TemporaryFolder and then creating KmlGroundOverlay and writing that to the same folder.&lt;/P&gt;&lt;P&gt;code snippet:&lt;/P&gt;&lt;LI-CODE lang="csharp"&gt;public async Task ExportGroundOverlay(StorageFolder folder, WriteableBitmap image, KmlPlacemark placemark, string filename)
        {
            try
            {
                //dont know why we need to flip these! but we do for change detection ground overlays.
                image = image.Flip(WriteableBitmapExtensions.FlipMode.Horizontal);

                foreach (char c in System.IO.Path.GetInvalidFileNameChars())
                {
                    filename = filename.Replace(c, '_');
                }

                StorageFile imageFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(filename + ".jpg", CreationCollisionOption.ReplaceExisting);
                using (IRandomAccessStream stream = await imageFile.OpenAsync(FileAccessMode.ReadWrite))
                {
                    await image.ToStream(stream, BitmapEncoder.JpegEncoderId);
                }

                KmlIcon icon = new KmlIcon(new Uri(imageFile.Path));
                
                KmlGroundOverlay groundOverlay = new KmlGroundOverlay(placemark.Geometries[0].Geometry, icon);
                StorageFile tempFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync(filename + ".kmz", CreationCollisionOption.ReplaceExisting);
                using (Stream stream = await tempFile.OpenStreamForWriteAsync())
                {
                    await groundOverlay.WriteToAsync(stream);
                }


                StorageFile file = await folder.CreateFileAsync(filename + ".kmz", CreationCollisionOption.ReplaceExisting);
                await tempFile.CopyAndReplaceAsync(file);
            }
            catch (Exception e)
            {
                Debug.WriteLine("ExportGroundOverlay() - exception = " + e.ToString());
            }
        }&lt;/LI-CODE&gt;</description>
      <pubDate>Mon, 03 May 2021 18:45:06 GMT</pubDate>
      <guid>https://community.esri.com/t5/net-maps-sdk-questions/kmlnode-writetoasync-doesnt-included-referenced/m-p/1053916#M10055</guid>
      <dc:creator>justinfernandes</dc:creator>
      <dc:date>2021-05-03T18:45:06Z</dc:date>
    </item>
  </channel>
</rss>

