docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Use case: Get thumbnail download URL for an annotation

    Before you start

    Before you download a thumbnail for an annotation, ensure you have completed the following prerequisites:

    1. Thumbnail Exists: The annotation must have a thumbnail already uploaded (check HasThumbnail property).
    2. Project Access: Ensure you have the necessary permissions to read annotations in the target project.
    3. Set Up SDK Environment: Confirm that your Unity environment is correctly configured with the Collaboration SDK.
    4. HTTP Client Ready: Prepare your HTTP client or Unity web request system to download from the URL.

    How do I...?

    Get a pre-signed URL to download a thumbnail

    To obtain a secure download URL for an annotation thumbnail, follow these steps:

    1. Verify Thumbnail Exists: Check that the annotation has HasThumbnail = true.
    2. Prepare Identifiers: Ensure you have the correct project and annotation identifiers.
    3. Request Download URL: Use the SDK to request a pre-signed download URL.
    4. Download Image: Use the returned URL to download the thumbnail image.
    5. Display or Process: Display the thumbnail in your UI or process it as needed.

    Example:

    var projectId = new ProjectId("87cf845f-8ca7-4b2f-9cc1-c3d731335810");
    var annotationId = new AnnotationId("a1b2c3d4-e5f6-7890-abcd-ef1234567890");
    
    var annotationReference = new annotationReference(projectId, annotationId);
    
    // Get the pre-signed download URL
    ReadThumbnailDownloadUrlResult result = await annotationManagement.ReadThumbnailDownloadUrlAsync(
        annotationReference,
        cancellationToken);
    
    string downloadUrl = result.Url;
    Debug.Log($"Thumbnail download URL: {downloadUrl}");
    
    // Download the thumbnail (see examples below)
    

    Download and display thumbnail in Unity

    Here's a complete example showing how to download and display a thumbnail as a Unity Texture2D:

    public async Task<Texture2D> DownloadAndDisplayThumbnail(
        ProjectId projectId,
        AnnotationId annotationId)
    {
        var annotationReference = new annotationReference(projectId, annotationId);
    
        try
        {
            // Step 1: Get the download URL
            ReadThumbnailDownloadUrlResult urlResult = await annotationManagement.ReadThumbnailDownloadUrlAsync(
                annotationReference,
                cancellationToken);
    
            Debug.Log($"Obtained download URL: {urlResult.Url}");
    
            // Step 2: Download the image
            using (UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(urlResult.Url))
            {
                await webRequest.SendWebRequest();
    
                if (webRequest.result != UnityWebRequest.Result.Success)
                {
                    Debug.LogError($"Failed to download thumbnail: {webRequest.error}");
                    return null;
                }
    
                // Step 3: Get the texture from the request
                Texture2D thumbnail = DownloadHandlerTexture.GetContent(webRequest);
                Debug.Log($"Thumbnail downloaded: {thumbnail.width}x{thumbnail.height}");
    
                return thumbnail;
            }
        }
        catch (Exception ex)
        {
            Debug.LogError($"Failed to download thumbnail: {ex.Message}");
            return null;
        }
    }
    
    // Usage:
    Texture2D thumbnail = await DownloadAndDisplayThumbnail(projectId, annotationId);
    if (thumbnail != null)
    {
        // Display in UI
        thumbnailImage.texture = thumbnail;
    }
    

    Check if thumbnail exists before downloading

    Always verify that a thumbnail exists before attempting to download:

    public async Task<Texture2D> DownloadThumbnailIfExists(
        ProjectId projectId,
        AnnotationId annotationId)
    {
        var annotationReference = new annotationReference(projectId, annotationId);
    
        // First, read the annotation to check if it has a thumbnail
        var annotationResult = await annotationManagement.ReadAnnotationAsync(
            annotationReference,
            cancellationToken: cancellationToken);
    
        if (!annotationResult.Annotation.HasThumbnail)
        {
            Debug.Log("Annotation does not have a thumbnail");
            return null;
        }
    
        // Thumbnail exists, proceed with download
        return await DownloadAndDisplayThumbnail(projectId, annotationId);
    }
    

    Download thumbnail with caching

    To avoid re-downloading thumbnails, implement caching:

    private Dictionary<string, Texture2D> thumbnailCache = new Dictionary<string, Texture2D>();
    
    public async Task<Texture2D> GetThumbnailWithCache(
        ProjectId projectId,
        AnnotationId annotationId)
    {
        string cacheKey = $"{projectId}_{annotationId}";
    
        // Check cache first
        if (thumbnailCache.TryGetValue(cacheKey, out Texture2D cachedThumbnail))
        {
            Debug.Log("Returning cached thumbnail");
            return cachedThumbnail;
        }
    
        // Download if not in cache
        Texture2D thumbnail = await DownloadAndDisplayThumbnail(projectId, annotationId);
    
        if (thumbnail != null)
        {
            thumbnailCache[cacheKey] = thumbnail;
            Debug.Log("Thumbnail cached");
        }
    
        return thumbnail;
    }
    
    public void ClearThumbnailCache()
    {
        foreach (var texture in thumbnailCache.Values)
        {
            if (texture != null)
            {
                Destroy(texture);
            }
        }
        thumbnailCache.Clear();
    }
    

    Download multiple thumbnails efficiently

    To download thumbnails for multiple annotations in parallel:

    public async Task<Dictionary<AnnotationId, Texture2D>> DownloadMultipleThumbnails(
        ProjectId projectId,
        List<AnnotationId> annotationIds)
    {
        var results = new Dictionary<AnnotationId, Texture2D>();
    
        // Create download tasks for all annotations
        var downloadTasks = annotationIds.Select(async annotationId =>
        {
            try
            {
                var thumbnail = await DownloadAndDisplayThumbnail(projectId, annotationId);
                return (annotationId, thumbnail);
            }
            catch (Exception ex)
            {
                Debug.LogWarning($"Failed to download thumbnail for {annotationId}: {ex.Message}");
                return (annotationId, (Texture2D)null);
            }
        });
    
        // Wait for all downloads to complete
        var downloadResults = await Task.WhenAll(downloadTasks);
    
        // Build results dictionary
        foreach (var (annotationId, thumbnail) in downloadResults)
        {
            if (thumbnail != null)
            {
                results[annotationId] = thumbnail;
            }
        }
    
        Debug.Log($"Downloaded {results.Count} thumbnails out of {annotationIds.Count}");
        return results;
    }
    

    Download thumbnail as byte array

    If you need the raw image data instead of a Texture2D:

    public async Task<byte[]> DownloadThumbnailAsBytes(
        ProjectId projectId,
        AnnotationId annotationId)
    {
        try
        {
            var annotationReference = new annotationReference(projectId, annotationId);
    
            // Get download URL
            ReadThumbnailDownloadUrlResult urlResult = await annotationManagement.ReadThumbnailDownloadUrlAsync(
                annotationReference,
                cancellationToken);
    
            // Download as bytes using HttpClient
            using (var httpClient = new HttpClient())
            {
                byte[] imageData = await httpClient.GetByteArrayAsync(urlResult.Url);
                Debug.Log($"Downloaded {imageData.Length} bytes");
                return imageData;
            }
        }
        catch (Exception ex)
        {
            Debug.LogError($"Failed to download thumbnail: {ex.Message}");
            return null;
        }
    }
    

    Handle download failures gracefully

    To provide fallback behavior when thumbnail download fails:

    public async Task<Texture2D> DownloadThumbnailWithFallback(
        ProjectId projectId,
        AnnotationId annotationId,
        Texture2D fallbackTexture)
    {
        try
        {
            var thumbnail = await DownloadAndDisplayThumbnail(projectId, annotationId);
            return thumbnail ?? fallbackTexture;
        }
        catch (Exception ex)
        {
            Debug.LogWarning($"Thumbnail download failed, using fallback: {ex.Message}");
            return fallbackTexture;
        }
    }
    
    // Usage with placeholder image:
    Texture2D placeholderImage = Resources.Load<Texture2D>("PlaceholderThumbnail");
    Texture2D thumbnail = await DownloadThumbnailWithFallback(
        projectId,
        annotationId,
        placeholderImage);
    

    Understanding pre-signed download URLs

    Pre-signed download URLs provide secure, temporary access to cloud storage:

    • Time-Limited: The URL expires after a certain period (typically minutes to hours)
    • Direct Download: Your application downloads directly from cloud storage, not through Unity servers
    • Secure: The URL includes authentication tokens, so no additional credentials are needed
    • GET Request: Use HTTP GET method to download from the pre-signed URL
    • No Authentication Headers: The URL is self-authenticated; don't add additional auth headers

    Best practices

    1. Check HasThumbnail First: Always verify the annotation has a thumbnail before requesting download URL
    2. Cache Thumbnails: Store downloaded thumbnails in memory or on disk to avoid redundant downloads
    3. Handle Expiration: If download fails, request a new URL rather than retrying with the expired URL
    4. Use Appropriate Size: Consider thumbnail dimensions for your UI needs
    5. Cleanup: Remember to destroy Texture2D objects when no longer needed to prevent memory leaks
    6. Error Handling: Provide fallback images or placeholder graphics when downloads fail
    7. Parallel Downloads: Use Task.WhenAll for downloading multiple thumbnails efficiently

    Common use cases

    • Annotation Lists: Display thumbnail previews in annotation list views
    • Detail Views: Show full thumbnail when user opens an annotation
    • Export/Reports: Include thumbnails in exported reports or documentation
    • Notifications: Show thumbnail previews in notification systems
    • Search Results: Display thumbnails in search result views

    For related operations, see documentation on uploading thumbnails and finalizing uploads.

    See the API documentation for more details on the ReadThumbnailDownloadUrlAsync method.

    In This Article
    Back to top
    Copyright © 2026 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)