ngel_lala
ngel_lala

Reputation: 5

Azure File is Detected Not Exist While It Actually Exists and Timeout Error

I want to move a video file from Azure Blob Storage to Sharepoint directly using C#. The code below does not work because there is a problem when getting the blobStream. I have ensured that my containerName and blobName are correct. However, when I checked the existence of the blobClient using blobClient.ExistAsync(), it always returns false. Does anyone know why a blob file cannot be detected while it actually existed in the Azure Blob Storage? Thanks in advance.

Here is the code that I implemented:

using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
using Microsoft.Graph;

namespace ZoomRecordingHelper
{
    public class GraphHandler
    {
        public GraphServiceClient GraphClient { get; set; }

        public GraphHandler()
        {
            var clientId = "";
            var clientSecret = "";
            var tenantId = "";

            var options = new TokenCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
            };

            var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
            var scopes = new[] { "https://graph.microsoft.com/.default" };

            GraphClient = new GraphServiceClient(clientSecretCredential, scopes);
        }

        public async Task UploadFileToSharePoint(string siteId, string driveId, string fileName, Stream fileStream)
        {
            try
            {
                var uploadUrl = $"https://graph.microsoft.com/v1.0/sites/{siteId}/drives/{driveId}/items/root:/{fileName}:/content";

                using (var httpClient = new HttpClient())
                {
                    var accessToken = await GetAccessTokenAsync();
                    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                    using (var httpRequest = new HttpRequestMessage(HttpMethod.Put, uploadUrl))
                    {
                        httpRequest.Content = new StreamContent(fileStream);
                        httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                        using (var response = await httpClient.SendAsync(httpRequest))
                        {
                            response.EnsureSuccessStatusCode();
                            Console.WriteLine("File uploaded successfully.");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error uploading file: {ex.Message}");
            }
        }
        
       public async Task<Stream> GetBlobStreamAsync(string connectionString, string containerName, string blobName)
        {
            var blobServiceClient = new BlobServiceClient(connectionString); // my conn string : DefaultEndpointsProtocol=https;AccountName=databinuscampussolution;AccountKey=xxxxxxxx;EndpointSuffix=core.windows.net

            var containerClient = blobServiceClient.GetBlobContainerClient(containerName); // my containerName : bm5

            var blobClient = containerClient.GetBlobClient(blobName); // my blobName : zoom/recording/BBS/2024-8-7/93116161045.mp4

            var isExist = await blobClient.ExistsAsync(); //always return false

        if (isExist.Value)
        {
            Console.WriteLine($"Start downloading blob {blobName}");
            var response = await blobClient.DownloadAsync();
            Console.WriteLine($"Finish downloaded blob {blobName}");

            return response.Value.Content;
        }
        else
        {
            Console.WriteLine($"Blob {blobName} does not exist in container {containerName}.");
            return null;
        }
        }

        private async Task<string> GetAccessTokenAsync()
        {
            var clientId = "";
            var clientSecret = "";
            var tenantId = "";

            var options = new TokenCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
            };

            var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
            var tokenRequestContext = new TokenRequestContext(new string[] { "https://graph.microsoft.com/.default" });

            var accessTokenResult = await clientSecretCredential.GetTokenAsync(tokenRequestContext);

            return accessTokenResult.Token;
        }
    }
}

The Not Found error is as follows:

{StatusCode: 404, ReasonPhrase: 'The specified blob does not exist.', Version: 1.1, Content: <null>, Headers:
{
  Transfer-Encoding: chunked
  Server: Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0
  x-ms-request-id: 53a1762c-901e-0025-3360-e93687000000
  x-ms-client-request-id: 78983a80-de24-44a4-b2ab-e8f34a5ce508
  x-ms-version: 2024-05-04
  x-ms-error-code: BlobNotFound
  Date: Thu, 08 Aug 2024 07:00:20 GMT
}}

I've just realized that my file is stored in Azure File Storage. Hence, I changed my GetBlobStreamAsync() to GetFileStreamAsync() as follows:

public async Task<Stream> GetFileStreamAsync(string connectionString, string sharedReference, string destFilePath, string fileName)
{
    var shareClient = new ShareClient(connectionString, sharedReference);
    ShareDirectoryClient directoryClient = shareClient.GetDirectoryClient(destFilePath);

    // Get a reference to the file
    ShareFileClient fileClient = directoryClient.GetFileClient(fileName);
    var isExist = fileClient.ExistsAsync().Result;

    try
    {
        if (isExist.Value)
        {
            // Get the file properties to determine the file size
            ShareFileProperties properties = await fileClient.GetPropertiesAsync();

            var response = await fileClient.DownloadAsync();

            return response.Value.Content;
        }
        else
        {
            //Console.WriteLine($"Blob {blobName} does not exist in container {containerName}.");
            return null;
        }
    }
    catch(Exception ex)
    {
        throw ex;
    }
    
}

The process of getting the Stream data is solved. Though, there is another Timeout error when uploading the Stream file to Sharepoint: Error:

System.Threading.Tasks.TaskCanceledException
  HResult=0x8013153B
  Message=The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
  Source=System.Net.Http
  StackTrace:
   at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)
   at System.Net.Http.HttpClient.<<SendAsync>g__Core|83_0>d.MoveNext()
   at Binus.LMS.Course2.BackEndAPI.ZoomRecordingScheduler.ZoomRecordingHelper.GraphHandler.<UploadFileToSharePoint>d__5.MoveNext() in C:\Users\angel\OneDrive\Desktop\Work\Backend\Course-Service\Course\Course2.BackEndAPI\ZoomRecordingScheduler\ZoomRecordingHelper\GraphHelper.cs:line 55

  This exception was originally thrown at this call stack:
    [External Code]

Inner Exception 1:
TimeoutException: The operation was canceled.

Inner Exception 2:
TaskCanceledException: The operation was canceled.

Upvotes: 0

Views: 69

Answers (1)

Venkatesan
Venkatesan

Reputation: 10370

However, when I checked the existence of the blobClient using blobClient.ExistAsync(), it always returns false. Does anyone know why a blob file cannot be detected while it actually existed in the Azure Blob Storage? .

I created a folder with the same name and filename as the one you have in your environment.

Portal:

enter image description here

Ensure that all parameters are correct and verify the code you're using, as incorrect parameters can cause error

I used the below code to copy file from azure blob storage to share point.

Code:

using System;
using System.IO;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Identity;
using Azure.Storage.Blobs;
using Microsoft.Graph;

namespace ZoomRecordingHelper
{
    class Program
    {
        static async Task Main(string[] args)
        {
            // Your Azure Blob Storage and SharePoint details
            string clientId = "your-client-id"; 
            string clientSecret = "your-client-secret";
            string tenantId = "your-tenant-id";
            string connectionString = "<storage connection string>";
            string containerName = "test";
            string siteId = "76ed9azzzzzz49c09e68adf";
            string driveId = "b!yprtdzzzzzzEK";
            string blobName = "zoom/recording/BBS/2024-8-7/93116161045.mp4";
            string fileName = "93116161045.mp4";

            var graphHandler = new GraphHandler(clientId, clientSecret, tenantId, connectionString, containerName);
            await graphHandler.MoveBlobToSharePointAsync(siteId, driveId, blobName, fileName);

            Console.WriteLine("Operation completed.");
        }
    }

    public class GraphHandler
    {
        private readonly GraphServiceClient _graphClient;
        private readonly string _connectionString;
        private readonly string _containerName;

        public GraphHandler(string clientId, string clientSecret, string tenantId, string connectionString, string containerName)
        {
            var options = new TokenCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
            };

            var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
            var scopes = new[] { "https://graph.microsoft.com/.default" };
            _graphClient = new GraphServiceClient(clientSecretCredential, scopes);

            _connectionString = connectionString;
            _containerName = containerName;
        }

        public async Task UploadFileToSharePointAsync(string siteId, string driveId, string fileName, Stream fileStream)
        {
            try
            {
                var uploadUrl = $"https://graph.microsoft.com/v1.0/sites/{siteId}/drives/{driveId}/items/root:/{fileName}:/content";

                using (var httpClient = new HttpClient())
                {
                    var accessToken = await GetAccessTokenAsync();
                    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                    using (var httpRequest = new HttpRequestMessage(HttpMethod.Put, uploadUrl))
                    {
                        httpRequest.Content = new StreamContent(fileStream);
                        httpRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                        using (var response = await httpClient.SendAsync(httpRequest))
                        {
                            response.EnsureSuccessStatusCode();
                            Console.WriteLine("File uploaded successfully.");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error uploading file: {ex.Message}");
            }
        }

        public async Task<Stream> GetBlobStreamAsync(string blobName)
        {
            var blobServiceClient = new BlobServiceClient(_connectionString);
            var containerClient = blobServiceClient.GetBlobContainerClient(_containerName);
            var blobClient = containerClient.GetBlobClient(blobName);

            try
            {
                var isExist = await blobClient.ExistsAsync();

                if (isExist.Value)
                {
                    Console.WriteLine($"Blob {blobName} exists. Start downloading.");
                    var response = await blobClient.DownloadAsync();
                    Console.WriteLine($"Finished downloading blob {blobName}");
                    return response.Value.Content;
                }
                else
                {
                    Console.WriteLine($"Blob {blobName} does not exist in container {_containerName}.");
                    return null;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error accessing blob {blobName}: {ex.Message}");
                return null;
            }
        }

        private async Task<string> GetAccessTokenAsync()
        {
            string clientId = "0xxxxxx2d-bc7c-65745880432b";
            string clientSecret = "Mrxxxxxxx3JdezBySHOc_V";
            string tenantId = "226xxxxxxx0283";

            var options = new TokenCredentialOptions
            {
                AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
            };

            var clientSecretCredential = new ClientSecretCredential(tenantId, clientId, clientSecret, options);
            var tokenRequestContext = new TokenRequestContext(new string[] { "https://graph.microsoft.com/.default" });

            var accessTokenResult = await clientSecretCredential.GetTokenAsync(tokenRequestContext);

            return accessTokenResult.Token;
        }

        public async Task MoveBlobToSharePointAsync(string siteId, string driveId, string blobName, string fileName)
        {
            var blobStream = await GetBlobStreamAsync(blobName);
            if (blobStream != null)
            {
                await UploadFileToSharePointAsync(siteId, driveId, fileName, blobStream);
                blobStream.Dispose(); // Dispose the stream after use
            }
            else
            {
                Console.WriteLine("Blob stream is null. Cannot upload to SharePoint.");
            }
        }
    }
}

Output:

Blob zoom/recording/BBS/2024-8-7/93116161045.mp4 exists. Start downloading.
Finished downloading blob zoom/recording/BBS/2024-8-7/93116161045.mp4
File uploaded successfully.
Operation completed.

enter image description here

.csproject:

<Project Sdk="Microsoft.NET.Sdk"> 
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Azure.Identity" Version="1.12.0" />
    <PackageReference Include="Azure.Storage.Blobs" Version="12.20.0" />
    <PackageReference Include="Microsoft.Graph" Version="5.56.0" />
  </ItemGroup>
</Project>

File: enter image description here

Upvotes: 0

Related Questions