Reputation: 5
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
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:
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.
.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:
Upvotes: 0