File Upload inclusion in Custom AEM Component for Remote Asset Selector | Community
Skip to main content
NageshRaja
Level 5
March 12, 2026
Solved

File Upload inclusion in Custom AEM Component for Remote Asset Selector

  • March 12, 2026
  • 5 replies
  • 72 views

Hi Team,


We are migrating all our assets to a separate AEM Cloud instance from a 3rd party DAM.

Our sites instance is setup in another program while the assets is on a different program,

 

We want to use our current components such that they are able to pull and render the assets remotely.

Following https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/assets/dynamicmedia/dynamic-media-open-apis/integrate-remote-approved-assets-with-sites# we are able to leverage image v3 component to fetch assets remotely.

However in our custom component we were not able to do so. The previous DAM image URLs were represented in these custom components as simple textfields.

We modified and added the below properties - 
Changing sling:resourceType from textfield to fileupload

sling:resourceType="cq/gui/components/authoring/dialog/fileupload"
enableNextGenDynamicMedia="{Boolean}true"
fileReferenceParameter="./fileReference"
fileNameParameter="./fileName"

On adding these values we are able to get the file upload option with both Remote and Local Asset Selector. 

When we select the image from remote repo the asset path is stored in JCR as “/urn:aaid:aem:0000bh81-2fc9-462a-9229-1234567890/e6252f18-ctc-iStock_000003487850Small.jpg”

 

The HTL for the component then renders the img with src=”/urn:aaid:aem...”

However, we want to expose the URL on the page as delivery URL or custom domain URL so that the image can actually load. 

What will be the best way to do so?

 

Thanks,

Nagesh

    Best answer by Rohan_Garg

    Hi ​@NageshRaja,

    If its a fixed mapping that you want you can do the below -

    Source URL - /urn:aaid:aem:0000bh81-2fc9-462a-9229-1234567890/e6252f18-ctc-iStock_000003487850Small.jpg”

    Target URL - https://delivery-p000001-e0000001.adobeaemcloud.com/adobe/assets/urn:aaid:aem:000a885c.../as/58fb9408-....png

    Please note you will not get responsive image optimisation which comes from Core Image like “?width=320&width=640&preferwebp=true” so essentially no resizing or responsive handling along with no automatic format optimisation, quality compression, smart imaging though it will be CDN backed. 

    You can make a fallback delivery URL using the config defined in - com.adobe.cq.ui.wcm.commons.internal.services.NextGenDynamicMediaConfigImpl.cfg.json


    To your existing method below - 
     if (image != null) {
                    LOG.info("resolveWithCoreImage(): Image isDMImage ={}", image.isDmImage());
                    String src = image.getSrc();
                    LOG.info("resolveWithCoreImage(): Core Image resolved src={}", src);
                    return src;
                }

    Add a return buildDeliveryUrl(assetPath);

    The delivery URL can be constructed as below - 

    String deliveryUrl = https:// + domain from config + “/adobe/assets” + existingBase + “/as” + lastSubstring;

    You can add update your Sling Delegation Pattern so src stops coming as null while having a fallback URL.

    Hope this helps!

     

    Thanks,

    Rohan Garg

    5 replies

    VishalKa5
    Level 6
    March 12, 2026

    Hi ​@NageshRaja ,

     

    In Adobe Experience Manager (AEM) Cloud Service, when using Remote Asset Selector, the selected asset is stored as a URN reference and not as a direct delivery URL. To render the image correctly in a custom component, you need to resolve that URN to a delivery URL.

    key points:

    1. URN Storage – Remote assets are stored in JCR as a URN (e.g., /urn:aaid:aem:...), not as a public image URL.

    2. URL Resolution Required – The URN must be resolved to the Dynamic Media delivery URL before rendering.

    3. Use Asset Delivery API / Service – Use the Dynamic Media or Asset Delivery service in backend (Sling Model/Java) to convert the URN into a delivery URL or custom domain URL.

    4. Update Sling Model – In your Sling Model, read the fileReference (URN) and resolve it to the delivery URL, then expose that value to HTL.

    5. HTL Rendering – Use the resolved delivery URL in HTL instead of directly printing the URN.

    6. Best Practice – Follow the same approach used by Core Components (Image v3), which internally resolves the URN before rendering the image.

    Conclusion:
    The best approach is to resolve the URN using the Asset Delivery/Dynamic Media service in a Sling Model and then pass the delivery URL to HTL for rendering.

    Thanks,
    Vishal

    NageshRaja
    Level 5
    March 12, 2026

    Hi ​@VishalKa5,

    I did use the sling model by injecting AssetDelivery OSGi service - 

    @OSGiServiceprivate AssetDelivery assetDelivery;
    options.put("path", assetPath);
    String deliveryUrl = assetDelivery.getDeliveryURL(resource, options);

     This however doesn’t yield the delivery URL.

    VishalKa5
    Level 6
    March 12, 2026

    Hi ​@NageshRaja,

    Hi @NageshRaja,

    If AssetDelivery.getDeliveryURL() is not returning the delivery URL, please check the following:

    1. URN vs Asset Path – The AssetDelivery service usually expects a valid DAM asset path, while the Remote Asset Selector stores a URN (/urn:aaid:aem:...), which may not resolve directly.

    2. Required Options – Ensure the options map includes required parameters like format, seoname, or other delivery settings depending on your configuration.

    3. Resource Context – Make sure the resource passed to getDeliveryURL() is the component resource or request resource with proper context.

    4. Remote Assets Limitation – For remote assets, the URN may need to be resolved through Dynamic Media/OpenAPI asset metadata before generating the delivery URL.

    5. Core Component Reference – It may help to check how the Image Core Component (v3) internally resolves remote asset references for delivery URLs.

    If possible, try logging the resolved asset metadata to confirm whether the URN is being correctly interpreted before calling getDeliveryURL().

    Thanks,
    Vishal

    AmitVishwakarma
    Community Advisor
    Community Advisor
    March 12, 2026

    HI ​@NageshRaja 

    The behavior you see is expected:

    • The fileReference for a remote asset is a URN (/urn:aaid:aem:...).
    • That value is not a delivery URL; it has to be resolved either by:
      • the Core Image component logic, or
      • the AssetDelivery API with the correct options.

    Your assetDelivery.getDeliveryURL(resource, options) call returns nothing because just putting "path" in a Map is not enough — the API expects specific option keys and values (delivery type, rendition/format, etc.) as described in the web‑optimized image API docs, not arbitrary keys. If those are missing or wrong, it will return null. https://experienceleague.adobe.com/en/docs/experience-manager-learn/cloud-service/developing/advanced/web-optimized-image-delivery-java-apis

     

    Instead of resolving the URN yourself, delegate to the Core Image component, which already knows how to turn the URN into a proper Dynamic Media / custom-domain URL:

    1. Make your custom component extend Image v3
      In your component definition: sling:resourceSuperType="core/wcm/components/image/v3/image"
    2. In your Sling Model, delegate to the Core Image model
      @Self
      @Via(type = ResourceSuperType.class)
      private com.adobe.cq.wcm.core.components.models.Image coreImage;

      public String getDeliveryUrl() {
      return coreImage != null ? coreImage.getSrc() : null;
      }
    3. In HTL, use the resolved URL
      <img src="${model.deliveryUrl}" alt="${coreImage.alt}"/>

      As long as remote assets + Dynamic Media OpenAPI are configured (ASSET_DELIVERY_REPOSITORY_ID, etc.), coreImage.getSrc() will output the final delivery URL or your custom domain URL, not the URN. https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/assets/dynamicmedia/dynamic-media-open-apis/integrate-remote-approved-assets-with-sites

    Don't print the /urn:aaid:aem:... directly. For custom components, the simplest working solution is to extend Core Image v3 (sling:resourceSuperType="core/wcm/components/image/v3/image") and in your Sling Model delegate to the Core Image model and use image.getSrc() in HTL. That method already converts the URN from fileReference into the proper Dynamic Media / custom-domain delivery URL, so your <img> tag gets a usable URL instead of a URN.

    Amit Vishwakarma - Adobe Commerce Champion 2025 | 16x Adobe certified | 4x Adobe SME
    NageshRaja
    Level 5
    March 17, 2026

    Hi ​@AmitVishwakarma, thank you for the response!

    For #1 - Delegating to the Core image model per my understanding will only work if the resource itself behaves like an image component. My custom component has multiple fileupload properties such as prop1, prop2 …
    So I can’t use a single delegated Image model that ways.

    I tried to adapt the request to the Core Image model based on the times fileupload properties are present. 
    Something like this below - 
    Sample path Input -  /urn:aaid:aem:000017e1-2fc9-462a-9229-5d72c3c8f3bf/e6252f18-ctc-iStock_000003487850Small.jpg

    if (isUrn(assetPath)) {
                Map<String, @Nullable Object> props = new HashMap<>();
                props.put("fileReference", assetPath);
                LOG.info("resolveWithCoreImage(): creating wrapper resource with fileReference={}", assetPath);

                SlingHttpServletRequest baseRequest = Objects.requireNonNull(request);

                Resource wrapped =
                        new ValueMapResource(
                                resource.getResourceResolver(),
                                resource.getPath(),
                                "core/wcm/components/image/v3/image",
                                new ValueMapDecorator(props)
                        );
                LOG.info("resolveWithCoreImage(): wrapped resource created");

                SlingHttpServletRequest wrappedRequest =
                        new org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper(baseRequest) {
                            @Override
                            public @NonNull Resource getResource() {
                                return wrapped;
                            }
                        };

                com.adobe.cq.wcm.core.components.models.Image image =
                        wrappedRequest.adaptTo(com.adobe.cq.wcm.core.components.models.Image.class);

                LOG.info("resolveWithCoreImage(): successfully adapted to Core Image model={}", image);

                if (image != null) {
                    LOG.info("resolveWithCoreImage(): Image isDMImage ={}", image.isDmImage());
                    String src = image.getSrc();
                    LOG.info("resolveWithCoreImage(): Core Image resolved src={}", src);
                    return src;
                }
            }

     

    However this has returned null on the src String.

    kautuk_sahni
    Community Manager
    Community Manager
    March 16, 2026

    @NageshRaja Following up to see if this has been resolved. If you’ve found the answer—whether through the suggestions here or through your own troubleshooting—feel free to post the solution so others can benefit. If any reply helped along the way, marking it as accepted ensures the most useful information is easy to find. Thanks for helping close the loop!

    Kautuk Sahni
    NageshRaja
    Level 5
    March 17, 2026

    @kautuk_sahni - I am still exploring the options but not getting tangible result. I will keep the thread updated!

    PGURUKRISHNA
    Level 4
    March 16, 2026

    Hey ​@NageshRaja 

    This is a common challenge when integrating Remote Assets (Dynamic Media with Open APIs) into custom AEM components. The core issue is that the JCR stores a URN reference (

    /urn:aaid:aem:...

    ), but you need to resolve it to an actual delivery URL.

    Here's the recommended approach:

    Use the 

    AssetDelivery

     API (Sling Model)

    AEM as a Cloud Service provides the 

    com.adobe.cq.wcm.spi.AssetDelivery

     OSGi service specifically for resolving remote asset URNs to delivery URLs. You should create a Sling Model that uses this service.

    1. Sling Model:

    package com.adobe.aem.guides.wknd.core.models;

    import com.adobe.cq.wcm.spi.AssetDelivery;
    import org.apache.sling.api.SlingHttpServletRequest;
    import org.apache.sling.api.resource.Resource;
    import org.apache.sling.models.annotations.Model;
    import org.apache.sling.models.annotations.injectorspecific.OSGiService;
    import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

    import javax.annotation.PostConstruct;
    import java.util.HashMap;
    import java.util.Map;

    @Model(adaptables = SlingHttpServletRequest.class)
    public class RemoteAssetModel {

    @OSGiService
    private AssetDelivery assetDelivery;

    @ValueMapValue(name = "fileReference", optional = true)
    private String fileReference;

    private String deliveryUrl;

    @PostConstruct
    protected void init() {
    if (fileReference != null && assetDelivery != null) {
    Map<String, Object> params = new HashMap<>();
    params.put("path", fileReference);
    params.put("format", "weboptimized");
    // Add width/quality params as needed:
    // params.put("width", 1280);
    // params.put("quality", 85);
    deliveryUrl = assetDelivery.getDeliveryURL(null, params);
    }
    }

    public String getDeliveryUrl() {
    return deliveryUrl;
    }

    public String getFileReference() {
    return fileReference;
    }
    }

     

     

    Note: The exact 

    AssetDelivery
     API signature may vary depending on your AEM SDK version. Check the latest Javadocs for 
    com.adobe.cq.wcm.spi.AssetDelivery
     in your SDK.

    2. HTL:

    <sly data-sly-use.model="com.adobe.aem.guides.wknd.core.models.RemoteAssetModel" />
    <sly data-sly-test="${model.deliveryUrl}">
    <img src="${model.deliveryUrl}" alt="" loading="lazy" />
    </sly>

     

    Alternative: NextGenDynamicMediaConfig

    If 

    AssetDelivery

     isn't available in your SDK version, you can resolve the URL manually by:

    1. Reading the 

      NextGenDynamicMediaConfig
       OSGi configuration to get the delivery base URL (the 
      repositoryId
       maps to 
      https://<repositoryId>/adobe/dynamicmedia/deliver/
      )
    2. Extracting the asset ID from the URN stored in 

      fileReference
    3. Constructing the URL: 

      https://<delivery-host>/adobe/dynamicmedia/deliver/<asset-id>/<seo-name>?width=1280&quality=85

    The URN format is typically 

    /urn:aaid:aem:<uuid>/<filename>

    , so you'd extract the UUID and filename to build the delivery URL.

    Key Recommendations

    • The 

      AssetDelivery
       API approach is preferred because it handles URL construction, CDN domain resolution, and any future format changes automatically.
    • Make sure your AEM Cloud environment has Dynamic Media with Open APIs enabled and the remote assets repository is configured under Tools → Cloud Services → Dynamic Media.

    • The Image v3 Core Component works because it already uses this same 

      AssetDelivery
       service internally — you're essentially replicating that pattern for your custom component.
    • Consider extending or delegating to the Core Image component (

      core/wcm/components/image/v3/image
      ) via 
      sling:resourceSuperType
       if your custom component is primarily an image component, rather than reimplementing the delivery URL logic.

     

     

    Pagidala GuruKrishna
    NageshRaja
    Level 5
    March 17, 2026

    Hi ​@PGURUKRISHNA, I have tried both AssetDelivery and Sling Delegation Pattern to the Core Image v3 model. Please refer the above comments for details. 

    None of them have returned the polaris API url for me. The image getSrc method shown below produces null when using delegation pattern as does getDeliveryURL() method.

    image.getSrc();

    String deliveryUrl = assetDelivery.getDeliveryURL(resource, options);

    Rohan_Garg
    Community Advisor
    Rohan_GargCommunity AdvisorAccepted solution
    Community Advisor
    March 17, 2026

    Hi ​@NageshRaja,

    If its a fixed mapping that you want you can do the below -

    Source URL - /urn:aaid:aem:0000bh81-2fc9-462a-9229-1234567890/e6252f18-ctc-iStock_000003487850Small.jpg”

    Target URL - https://delivery-p000001-e0000001.adobeaemcloud.com/adobe/assets/urn:aaid:aem:000a885c.../as/58fb9408-....png

    Please note you will not get responsive image optimisation which comes from Core Image like “?width=320&width=640&preferwebp=true” so essentially no resizing or responsive handling along with no automatic format optimisation, quality compression, smart imaging though it will be CDN backed. 

    You can make a fallback delivery URL using the config defined in - com.adobe.cq.ui.wcm.commons.internal.services.NextGenDynamicMediaConfigImpl.cfg.json


    To your existing method below - 
     if (image != null) {
                    LOG.info("resolveWithCoreImage(): Image isDMImage ={}", image.isDmImage());
                    String src = image.getSrc();
                    LOG.info("resolveWithCoreImage(): Core Image resolved src={}", src);
                    return src;
                }

    Add a return buildDeliveryUrl(assetPath);

    The delivery URL can be constructed as below - 

    String deliveryUrl = https:// + domain from config + “/adobe/assets” + existingBase + “/as” + lastSubstring;

    You can add update your Sling Delegation Pattern so src stops coming as null while having a fallback URL.

    Hope this helps!

     

    Thanks,

    Rohan Garg

    NageshRaja
    Level 5
    March 19, 2026

    Thanks a lot ​@Rohan_Garg for this suggestion!

    But something to add here that this URL made manually does have responsive image optimization.

    width=550&preferwebp=true || width=550&height=300 both of these are able to scale the image!