Search code examples
c#azureazure-functionsazure-storage

How to change the name of the blob file when transferring it from one container to another?


I am creating an azure function that has a blob trigger. When the blob is uploaded, it is encrypted and transferred to another container. The issue I am facing is that when i transfer the blob to the second container the name of the blob file is the same and the only thing i was capable of doing is adding ".pgp" at the end of the file name. I would like to trim the last 4 characters of the blob (.txt) and replace them with .pgp.

The following is my code:

namespace EncryptAndTransfer
{
    public class EncryptAndTransfer
    {
        [FunctionName("EncryptAndTransfer")]
        public async Task Run([BlobTrigger("send-decrypted/{name}", Connection = "bctofabstorgacc_Storage")]Stream myBlob, 
            string name,
            [Blob("send-encrypted/{name}.pgp", FileAccess.Write, Connection = "bctofabstorgacc_Storage")] Stream outBlob,
            [Blob("send-decrypted/fabtraderhubtest.asc", FileAccess.Read, Connection = "bctofabstorgacc_Storage")] Stream publicKeyBlob,
            ILogger log)
        {
            //Getting the secrets required for the function
            var azureServiceTokenProvider = new AzureServiceTokenProvider();
            var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
            
            // Load the public key
            PgpPublicKey publicKey = LoadPublicKey(publicKeyBlob, log);

            if (publicKey == null)
            {
                log.LogError("Failed to load the public key.");
                return;
            }
            // Encrypt the content
            byte[] encryptedData = EncryptData(myBlob, publicKey, log);
            // Write the encrypted content to the output blob
            outBlob.Write(encryptedData, 0, encryptedData.Length);
        }
        private static PgpPublicKey LoadPublicKey(Stream publicKeyStream, ILogger log)
        {
            try
            {
                using (StreamReader reader = new StreamReader(publicKeyStream, Encoding.ASCII))
                {
                    PgpPublicKeyRing publicKeyRing = new PgpPublicKeyRing(
                        PgpUtilities.GetDecoderStream(reader.BaseStream)
                    );
                    PgpPublicKey publicKey = publicKeyRing.GetPublicKeys().OfType<PgpPublicKey>().FirstOrDefault();
                    if (publicKey != null)
                    {
                        return publicKey;
                    }
                }
            }
            catch (PgpException ex)
            {
                log.LogError("PgpException caught in LoadPublicKey: " + ex.Message);
            }
            catch (IOException ex)
            {
                log.LogError("IOException caught in LoadPublicKey: " + ex.Message);
            }
            return null;
        }

        private static byte[] EncryptData(Stream inputData, PgpPublicKey publicKey, ILogger log)
        {
            try
            {
                using (MemoryStream encryptedStream = new MemoryStream())
                {
                    // Create the encrypted data generator
                    PgpEncryptedDataGenerator encryptedDataGenerator = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Aes256, true);
                    // Add the public key to the encrypted data generator
                    encryptedDataGenerator.AddMethod(publicKey);
                    // Create an output stream connected to the encrypted data generator
                    using (Stream outputStream = encryptedDataGenerator.Open(encryptedStream, new byte[1 << 16]))
                    {
                        // Copy the input data to the output stream
                        inputData.CopyTo(outputStream);
                    }
                    // Return the encrypted data
                    return encryptedStream.ToArray();
                }
            }
            catch (Exception ex)
            {
                log.LogError("Exception caught in EncryptData: " + ex.Message);
                throw; // rethrow the exception after logging
            }
        }
    }
}

I have tried to add .pgp to the output blob which worked but i cannot remove the .txt from it.


Solution

  • How to change the name of the blob file when transferring it from one container to another?

    This is not possible. Renaming is not supported and also refer this SO-thread.

    Alternatively to change name, Firstly, you can use your code and send the file to temporary container2.

    Whenever a blob comes in container2 with more than one extension in name, use below function and send the renamed file to container3:

    But if you want to rename a blob use this function:

    using System;
    using System.IO;
    using System.Threading.Tasks;
    using Azure.Storage.Blobs;
    using Microsoft.Azure.WebJobs;
    using Microsoft.Azure.WebJobs.Host;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.Logging;
    
    namespace FunctionApp72
    {
        public class Function1
        {
            private readonly IConfiguration configg;
            public Function1(IConfiguration configuration)
            {
    
                configg = configuration;
            }
    
            [FunctionName("Function1")]
    
            public async Task Run([BlobTrigger("test/{name}", Connection = "rithcon")] Stream myBlob, string name, ILogger log)
            {
                using var blobStreamReader = new StreamReader(myBlob);
                var data = await blobStreamReader.ReadToEndAsync();
                string withoutext1 = RemoveExtension(name);
    
                Console.WriteLine($"Uploaded File Name: {name}");
                Console.WriteLine($"After removing unwanted extensions: {withoutext1}");
    
                string value = configg.GetValue<string>("rithcon");
                var bsc = new BlobServiceClient(value);
                var bcc = bsc.GetBlobContainerClient("test2");
                var bc = bcc.GetBlobClient(withoutext1);
    
                using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(data)))
                {
                    await bc.UploadAsync(stream, true);
                }
    
                // Delete the original blob
                var obc = bcc.GetBlobClient(name);
            await obc.DeleteIfExistsAsync();
        }
    
                static string RemoveExtension(string fn)
            {
               int Index = fn.LastIndexOf('.');
    
                if (Index != -1)
                {
                    string dir = Path.GetDirectoryName(fn);
                    string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fn);
    
                    int firDIndex = fileNameWithoutExtension.IndexOf('.');
    
                    if (firDIndex != -1)
                    {
                        fileNameWithoutExtension = fileNameWithoutExtension.Substring(0, firDIndex);
                    }
                    fn = Path.Combine(dir, $"{fileNameWithoutExtension}{Path.GetExtension(fn)}");
                }
    
                return fn;
            }
        }
    }
    

    Uploaded file to test container:

    enter image description here

    Output:

    In container 3 test2 file name is changed:

    enter image description here