Media Files/Form Attachments in Different Azure Storage

Although I can programmatically upload files to the blob storage, I would like to be able to separate Form Attachments from all other media and have each in a different location.

I’m not sure if this is possible.

It seems the only option is to have all media (including form attachments) in one place.

Can anyone shed light on this?

I’ve been trying to achieve the same thing and have just about come to the same conclusion.

Not sure if you’ve found a solution, but I am currently trying to do it with a custom workflow type - which looks like it should work (I’m just trying to win a fight with a local proxy server that’s blocking me at the moment)

Hope this helps. Sorry not to get back sooner.

I created a class using IBlobService

public class [classname] : IBlobservice
{
private readonly string _connectionString;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly string _blobkey;

 public BlobService(string connectionString, IHttpContextAccessor httpContextAccessor, IConfiguration configuration)
 {
     _connectionString = connectionString;
     _httpContextAccessor = httpContextAccessor;
     _blobkey = configuration[using_path_to_appsettings];
 }
public async Task<List<string>> UploadFileAsync(List<IFormFile> filePath, string containerName, string formId, string getFilenames)
{
  var blobServiceClient = new BlobServiceClient(_connectionString);
  var blobContainerClient =
blobServiceClient.GetBlobContainerClient("formstostore");
string fileNames = "";
string fileNamesToStore = "";
List<string> files = new List<string>();
        foreach (var file in filePath)
        {            
            var newFilename = Guid.NewGuid().ToString() + "_" + file.FileName;
            files.Add(newFilename);

            string format = Path.GetExtension(file.FileName);
            var blobClient = blobContainerClient.GetBlobClient(formId + "/" + newFilename);

            string sasUrl = "";
            try
            {
                Azure.Storage.Sas.BlobSasBuilder blobSasBuilder = new Azure.Storage.Sas.BlobSasBuilder()
                {
                    BlobContainerName = "formstostore",
                    BlobName = newFilename,
                    ExpiresOn = DateTime.UtcNow.AddDays(7300)
                };
                blobSasBuilder.SetPermissions(Azure.Storage.Sas.BlobSasPermissions.Read);
                var sasToken = blobSasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(containerName, _blobkey)).ToString();
                sasUrl = blobClient.Uri.AbsoluteUri + "?" + sasToken;
            }
            catch (Exception ex)
            { }


            if (fileNames == "")
            {
                if(getFilenames != "")
                {
                    fileNames = getFilenames + "/" + file.FileName;
                    fileNamesToStore = getSession + "__" + Environment.NewLine + sasUrl;
                }
                else
                {
                    fileNames = file.FileName;
                    fileNamesToStore = sasUrl;
                }
            }
            else
            {
               fileNames = fileNames + "/" + file.FileName;
               fileNamesToStore =   fileNamesToStore + "__" + Environment.NewLine + sasUrl ;
            }

         blobClient.UploadAsync(file.OpenReadStream(), overwrite: true);
System.Threading.Thread.Sleep(2000);
         
    }                   
            return files;
}


I created a FormField extending Umbraco.forms.Core.Providers.FieldTypes.FileUpload and in the ValidateField I created a new variable List then looped through context.Request.FormFiles and added each file to the List.

I also had to create a session to identify the filenames (I couldn’t get another way to capture the filenames)

public async Task<List<string>> getNewFilenames(HttpContext context, List<IFormFile> files,string getFilenames)
{
    List<string> getFilenamesNew = new List<string>();
    string FormId = "";

    if (files.Count > 0)
    {
        var getFormId = context.Request.Form.ElementAt(0);

        foreach(var element in context.Request.Form)
        {
            if(element.Key == "FormId")
            {
                FormId = element.Value;
            }
        }
     
        var blobService = new BlobService(_blobconn, _httpContextAccessor, _configuration);
        getFilenamesNew = await blobService.UploadFileAsync(files, _blobcontainername,FormId,getFilenames);

        return getFilenamesNew;
    }

    return getFilenamesNew;
}

Also, when calling blobClient.UploadAsync(file.OpenreadStream(),overwrite: true);

I had to call Sleep(2000). In my case, Azure was slow in storing the file so this gave it time. I’m sure there is another way to counter this but it was the best solution for now.