Why won't anything upload? - Uploading info blob to Azure with Xamarin - azure

I have been trying for quite some time to get something to upload to my Azure blob container I have set up with an Xamarin.ios project.
I am not sure why it isn't working, and have explored many different options.
I get CS0426 whenever I try and refer to LimaBeans in my Viewcontroller.
Stumped.
This is my View Controller
using System;
using System.IO;
using UIKit;
namespace storingbuttondataaaa
{
public partial class ViewController : UIViewController
{
protected ViewController(IntPtr handle) : base(handle)
{
// Note: this .ctor should not contain any initialization logic.
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
// Perform any additional setup after loading the view, typically from a nib.
}
public override void DidReceiveMemoryWarning()
{
base.DidReceiveMemoryWarning();
// Release any cached data, images, etc that aren't in use.
}
partial void FractureBtn_TouchUpInside(UIButton sender)
{
//get text box data
var name = FractureBtn;
string call = ("call 911, especially if blood is spraying everywhere!");
string line = string.Format("{0},{1}", name, call);
//Store the Information.
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filename = Path.Combine(documents, "HealthJournal.txt");
File.WriteAllText(filename, line);
;
}
partial void HandleAddClicked_TouchUpInside(UIButton sender)
{
activityIndicator.StartAnimating();
new BlobUpload.LimaBeans();
}
}
}
and this is my blob upload task:
using System;
using System.Diagnostics.Contracts;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
namespace storingbuttondataaaa
{
public class BlobUpload
{
public BlobUpload()
{
}
public static async Task LimaBeans(string localPath)
{
Contract.Ensures(Contract.Result<Task>() != null);
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=itsmypersonalkey");
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("submittedreqforbd");
// Create the container if it doesn't already exist.
await container.CreateIfNotExistsAsync();
// Retrieve reference to a blob named "myblob".
CloudBlockBlob blockBlob = container.GetBlockBlobReference("myblob");
//await blockBlob.UploadFromFileAsync(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
await blockBlob.UploadTextAsync("My Head Just Exploaded!");
}
}
}
What is wrong? I am on the verge of giving up!

No defining declaration found for implementing declaration of partial method ViewController.FractureBtn_TouchUpInside(UIButton)
We should define a declaration of this method in another partial class as below:
partial void FractureBtn_TouchUpInside(UIButton sender);
To upload local file to Azure, we can do as below:
/// <summary>
/// Upload file to Blob
/// </summary>
/// <param name="path">path of local file. For example: C:\Users\leel2\Desktop\333.txt</param>
/// <param name="blobName">For example: 333.txt</param>
/// <param name="containerName"></param>
public static void UploadBlob(string path, string blobName, string containerName)
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=xxxxxxxx");
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = cloudBlobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
blob.UploadFromFile(path);
}

Related

Blazor server side upload file to Azure Blob Storage

I am using a file upload component that posts the file to an API controller and this works ok but i need to get the progres of the upload.
[HttpPost("upload/single")]
public async Task SingleAsync(IFormFile file)
{
try
{
// Azure connection string and container name passed as an argument to get the Blob reference of the container.
var container = new BlobContainerClient(azureConnectionString, "upload-container");
// Method to create our container if it doesn’t exist.
var createResponse = await container.CreateIfNotExistsAsync();
// If container successfully created, then set public access type to Blob.
if (createResponse != null && createResponse.GetRawResponse().Status == 201)
await container.SetAccessPolicyAsync(Azure.Storage.Blobs.Models.PublicAccessType.Blob);
// Method to create a new Blob client.
var blob = container.GetBlobClient(file.FileName);
// If a blob with the same name exists, then we delete the Blob and its snapshots.
await blob.DeleteIfExistsAsync(Azure.Storage.Blobs.Models.DeleteSnapshotsOption.IncludeSnapshots);
// Create a file stream and use the UploadSync method to upload the Blob.
uploadFileSize = file.Length;
var progressHandler = new Progress<long>();
progressHandler.ProgressChanged += UploadProgressChanged;
using (var fileStream = file.OpenReadStream())
{
await blob.UploadAsync(fileStream, new BlobHttpHeaders { ContentType = file.ContentType },progressHandler:progressHandler);
}
Response.StatusCode = 400;
}
catch (Exception e)
{
Response.Clear();
Response.StatusCode = 204;
Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "File failed to upload";
Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = e.Message;
}
}
private double GetProgressPercentage(double totalSize, double currentSize)
{
return (currentSize / totalSize) * 100;
}
private void UploadProgressChanged(object sender, long bytesUploaded)
{
uploadPercentage = GetProgressPercentage(uploadFileSize, bytesUploaded);
}
I am posting this file and it does upload but the file upload progress event is inaccurate it says the file upload is complete after a few seconds when in reality the file takes ~90 secs on my connection to appear in the Azure Blob Storage container.
So in the code above i have the progress handler which works (I can put a break point on it and see it increasing) but how do I return this value to the UI?
I found one solution that used Microsoft.AspNetCore.SignalR but I can't manage to integrate this into my own code and I'm not even sure if I'm on the right track.
using BlazorReportProgress.Server.Hubs;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using System.Threading;
namespace BlazorReportProgress.Server.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class SlowProcessController : ControllerBase
{
private readonly ILogger<SlowProcessController> _logger;
private readonly IHubContext<ProgressHub> _hubController;
public SlowProcessController(
ILogger<SlowProcessController> logger,
IHubContext<ProgressHub> hubContext)
{
_logger = logger;
_hubController = hubContext;
}
[HttpGet("{ClientID}")]
public IEnumerable<int> Get(string ClientID)
{
List<int> retVal = new();
_logger.LogInformation("Incoming call from ClientID : {ClientID}", ClientID);
_hubController.Clients.Client(ClientID).SendAsync("ProgressReport", "Starting...");
Thread.Sleep(1000);
for (int loop = 0; loop < 10; loop++)
{
_hubController.Clients.Client(ClientID).SendAsync("ProgressReport", loop.ToString());
retVal.Add(loop);
Thread.Sleep(500);
}
_hubController.Clients.Client(ClientID).SendAsync("ProgressReport", "Done!");
return retVal;
}
}
}
I read the Steve Sandersen blog but this says not to use the code as its been superceded by inbuilt blazor functionality.
My application is only for a few users and so i'm not too worried about backend APIs etc, If the upload component used a service not a controller I could more easily get the progress, but the compoents all seem to post to controllers.
Can anyone please enlighten me as to the best way to solve this?

How do I access blob storage sub containers in my ASP.NET Core web application?

I've created a solution to access my container contents within my asp.net core 3.1 application and return that contents as a list to my view. At the moment the application access data in the root container which is called upload, however, this container has many sub containers and I would like to list the blobs in a specific one called 1799.
So, instead of accessing upload and showing me the full contents of that container, I want to access upload/1799 and list all the blobs within that container.
I cannot see of anyway to add this sub container to my method and allow this to happen, can anyone help?
Here is my code so far:
CarController.cs
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
namespace MyProject.Controllers
{
public class HomeController : Controller
{
private readonly IConfiguration _configuration;
private readonly string accessKey = string.Empty;
public HomeController(IConfiguration configuration)
{
_configuration = configuration;
accessKey = _configuration.GetConnectionString("AzureStorage");
}
[HttpGet]
public IActionResult Edit(int id)
{
var car = _carService.GetVessel(id);
string strContainerName = "uploads";
string subdir = "1799";
var filelist = new List<BlobListViewModel>();
BlobServiceClient blobServiceClient = new BlobServiceClient(accessKey);
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(strContainerName);
var blobs = containerClient.GetBlobs();
foreach (var item in blobs)
{
filelist.Add(new BlobListViewModel
{
FileName = item.Name
});
}
return View(filelist);
}
}
I've hunted through all the documentation and I can't find anything related to this.
Thanks to David Browne for his comment, there is indeed a prefix option in GetBlob(). THey act like mini-filters in some ways allowing you to define what properties are returned and the blob state etc. Here is my code which has the options set to zero meaning Default for both Trait and State.
[HttpGet]
public IActionResult Edit(int id)
{
var car = _carService.GetVessel(id);
string strContainerName = "uploads";
string subdir = "1799";
var filelist = new List<BlobListViewModel>();
BlobServiceClient blobServiceClient = new BlobServiceClient(accessKey);
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(strContainerName);
//Traits, States, Prefix
var blobs = containerClient.GetBlobs(0, 0, subdir);
foreach (var item in blobs)
{
filelist.Add(new BlobListViewModel
{
FileName = item.Name
});
}
return View(filelist);
}

Transferring files from previously deleted azure media service to new media service- is it possible?

Is it possible to transfer files from an old media service account which has been accidentally deleted to a new media services account.
Microsoft tech support have been no help.
I'm able to copy over the files to the new media service account, but when i test to see if I can publish one of the assets in the portal, It gives me successful streaming urls, but when I try to access those I get a network error
<serverError>
<status>404</status>
<subStatus>1000</subStatus>
<hresult>MPE_STORAGE_RESOURCE_NOT_FOUND</hresult>
<activityId>80028340-0004-F800-B63F-84710C7967BB</activityId>
<serviceId>4A42CB8E-4542-0C18-2C0D-4B460D96B604</serviceId>
</serverError>
I don't think it can find the manifest file. which is named pc124m190o_AdaptiveStreaming_manifest.xml
The name of the metadata file could also be a potential problem
5f7e8f45-87e9-49ce-a2ae-7bb673bf0b0f_metadata.xml
has anyone successfully done this?
Here is the code I'm using to copy the files. Maybe the error is here?
class Program
{
// Read values from the App.config file.
private static readonly string _sourceStorageAccountName =
ConfigurationManager.AppSettings["SourceStorageAccountName"];
private static readonly string _sourceStorageAccountKey =
ConfigurationManager.AppSettings["SourceStorageAccountKey"];
private static readonly string _NameOfBlobContainerYouWantToCopy =
ConfigurationManager.AppSettings["NameOfBlobContainerYouWantToCopy"];
private static readonly string _AMSAADTenantDomain =
ConfigurationManager.AppSettings["AMSAADTenantDomain"];
private static readonly string _AMSRESTAPIEndpoint =
ConfigurationManager.AppSettings["AMSRESTAPIEndpoint"];
private static readonly string _AMSClientId =
ConfigurationManager.AppSettings["AMSClientId"];
private static readonly string _AMSClientSecret =
ConfigurationManager.AppSettings["AMSClientSecret"];
private static readonly string _AMSStorageAccountName =
ConfigurationManager.AppSettings["AMSStorageAccountName"];
private static readonly string _AMSStorageAccountKey =
ConfigurationManager.AppSettings["AMSStorageAccountKey"];
// Field for service context.
private static CloudMediaContext _context = null;
private static CloudStorageAccount _sourceStorageAccount = null;
private static CloudStorageAccount _destinationStorageAccount = null;
static void Main(string[] args)
{
AzureAdTokenCredentials tokenCredentials = new AzureAdTokenCredentials(_AMSAADTenantDomain,
new AzureAdClientSymmetricKey(_AMSClientId, _AMSClientSecret),
AzureEnvironments.AzureCloudEnvironment);
var tokenProvider = new AzureAdTokenProvider(tokenCredentials);
// Create the context for your source Media Services account.
_context = new CloudMediaContext(new Uri(_AMSRESTAPIEndpoint), tokenProvider);
_sourceStorageAccount =
new CloudStorageAccount(new StorageCredentials(_sourceStorageAccountName,
_sourceStorageAccountKey), true);
_destinationStorageAccount =
new CloudStorageAccount(new StorageCredentials(_AMSStorageAccountName,
_AMSStorageAccountKey), true);
CloudBlobClient sourceCloudBlobClient =
_sourceStorageAccount.CreateCloudBlobClient();
// CreateAssetFromExistingBlobs(sourceContainer);
List<string> containers=GetAllContainerNames(sourceCloudBlobClient);
foreach(string item in containers)
{
CloudBlobContainer sourceContainer =
sourceCloudBlobClient.GetContainerReference(item);
CreateAssetFromExistingBlobs(sourceContainer);
Console.WriteLine("finished " + item);
}
}
static private IAsset CreateAssetFromExistingBlobs(CloudBlobContainer sourceBlobContainer)
{
CloudBlobClient destBlobStorage = _destinationStorageAccount.CreateCloudBlobClient();
// Create a new asset.
IAsset asset = _context.Assets.Create("NewAsset_" + Guid.NewGuid(), AssetCreationOptions.None);
IAccessPolicy writePolicy = _context.AccessPolicies.Create("writePolicy",
TimeSpan.FromHours(24), AccessPermissions.Write);
ILocator destinationLocator =
_context.Locators.CreateLocator(LocatorType.Sas, asset, writePolicy);
// Get the asset container URI and Blob copy from mediaContainer to assetContainer.
CloudBlobContainer destAssetContainer =
destBlobStorage.GetContainerReference((new Uri(destinationLocator.Path)).Segments[1]);
if (destAssetContainer.CreateIfNotExists())
{
destAssetContainer.SetPermissions(new BlobContainerPermissions
{
PublicAccess = BlobContainerPublicAccessType.Blob
});
}
var blobList = sourceBlobContainer.ListBlobs();
foreach (CloudBlockBlob sourceBlob in blobList)
{
var assetFile = asset.AssetFiles.Create((sourceBlob as ICloudBlob).Name);
ICloudBlob destinationBlob = destAssetContainer.GetBlockBlobReference(assetFile.Name);
CopyBlob(sourceBlob, destAssetContainer);
sourceBlob.FetchAttributes();
assetFile.ContentFileSize = (sourceBlob as ICloudBlob).Properties.Length;
assetFile.Update();
Console.WriteLine("File {0} is of {1} size", assetFile.Name, assetFile.ContentFileSize);
}
asset.Update();
destinationLocator.Delete();
writePolicy.Delete();
// Set the primary asset file.
// If, for example, we copied a set of Smooth Streaming files,
// set the .ism file to be the primary file.
// If we, for example, copied an .mp4, then the mp4 would be the primary file.
var ismAssetFile = asset.AssetFiles.ToList().
Where(f => f.Name.EndsWith(".ism", StringComparison.OrdinalIgnoreCase)).ToArray().FirstOrDefault();
// The following code assigns the first .ism file as the primary file in the asset.
// An asset should have one .ism file.
if (ismAssetFile != null)
{
ismAssetFile.IsPrimary = true;
ismAssetFile.Update();
}
return asset;
}
Here is what my media storage window looks like
The manifest file you mentioned is technically not required for streaming. What is missing is that when you copied the files to your new Storage account the new Media Services account knows nothing of them. You must create new assets and copy the files into the new assets for Media Services to see them. I recommend doing an import with Azure Media Services Explorer in your new account from the Storage account.

How to upload a file to a storage location through URL using Azure function app

I want to upload the upload a file to a storage location through URL using Azure function app from Azure blob storage. I'm able to pull the file from Azure blob. But not able to upload the file through url.
Below I have attached the code which i have written. Could anyone help me on this?
#r "Newtonsoft.Json"
#r "Microsoft.WindowsAzure.Storage"
#r "System.IO"
using System;
using System.IO;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.Auth;
using System.Xml;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Net;
public static void Run(string input, TraceWriter log)
{
log.Info($"C# manual trigger function processed\n");
const string StorageAccountName = "";
const string StorageAccountKey = "";
var storageAccount = new CloudStorageAccount(new StorageCredentials(StorageAccountName, StorageAccountKey), true);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("hannahtest");
var Destcontainer = blobClient.GetContainerReference("hannahtestoutput");
var blobs = container.ListBlobs();
log.Info($"Creating Client and Connecting");
foreach (IListBlobItem item in container.ListBlobs(null, false))
{
if (item is CloudBlockBlob blockBlob)
{
using (StreamReader reader = new StreamReader(blockBlob.OpenRead())
{
//old content string will read the blockblob (xml)till end
string oldContent1 = reader.ReadToEnd();
log.Info(oldContent1);
var content = new FormUrlEncodedContent(oldContent1);
var response = await client.PostAsync("http://www.example.com/recepticle.aspx", content);
var responseString = await response.Content.ReadAsStringAsync();
log.Info($"Success");
}
}
}
}
Have a look at Blob Output Binding - that's how the blobs are intended to be uploaded from Azure Functions, without messing with Azure Storage SDK.
Azure function to upload multiple image file to blob storage.
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
public static class ImageUploadFunction
{
[FunctionName("ImageUploadFunction")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "post")]HttpRequestMessage req, ILogger log)
{
var provider = new MultipartMemoryStreamProvider();
await req.Content.ReadAsMultipartAsync(provider);
var files = provider.Contents;
List<string> uploadsurls = new List<string>();
foreach (var file in files) {
var fileInfo = file.Headers.ContentDisposition;
Guid guid = Guid.NewGuid();
string oldFileName = fileInfo.FileName;
string newFileName = guid.ToString();
var fileExtension = oldFileName.Split('.').Last().Replace("\"", "").Trim();
var fileData = await file.ReadAsByteArrayAsync();
try {
//Upload file to azure blob storage method
var upload = await UploadFileToStorage(fileData, newFileName + "." + fileExtension);
uploadsurls.Add(upload);
}
catch (Exception ex) {
log.LogError(ex.Message);
return new BadRequestObjectResult("Somthing went wrong.");
}
}
return uploadsurls != null
? (ActionResult)new OkObjectResult(uploadsurls)
: new BadRequestObjectResult("Somthing went wrong.");
}
private static async Task<string> UploadFileToStorage(byte[] fileStream, string fileName)
{
// Create storagecredentials object by reading the values from the configuration (appsettings.json)
StorageCredentials storageCredentials = new StorageCredentials("<AccountName>", "<KeyValue>");
// Create cloudstorage account by passing the storagecredentials
CloudStorageAccount storageAccount = new CloudStorageAccount(storageCredentials, true);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Get reference to the blob container by passing the name by reading the value from the configuration (appsettings.json)
CloudBlobContainer container = blobClient.GetContainerReference("digital-material-library-images");
// Get the reference to the block blob from the container
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
// Upload the file
await blockBlob.UploadFromByteArrayAsync(fileStream,0, fileStream.Length);
blockBlob.Properties.ContentType = "image/jpg";
await blockBlob.SetPropertiesAsync();
return blockBlob.Uri.ToString();
//return await Task.FromResult(true);
}
}

C# Azure storage from one blob copy file to another blob

How can I read a file to stream from one blob and upload to another blob? My requirement is to copy a file from one blob to another blob with different file name? In C#
The easiest way to achieve it is using "Azure Storage Data Movement Library" (you can get it thru nuget package).
This is a simple-sample to make the transfer:
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Microsoft.WindowsAzure.Storage.DataMovement;
using System;
namespace BlobClient
{
class Program
{
static void Main(string[] args)
{
const string storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=juanktest;AccountKey=loHQwke4lSEu1p2W3gg==";
const string container1 = "juankcontainer";
const string sourceBlobName = "test.txt";
const string destBlobName = "newTest.txt";
//Setup Account, blobclient and blobs
CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference(container1);
blobContainer.CreateIfNotExists();
CloudBlockBlob sourceBlob = blobContainer.GetBlockBlobReference(sourceBlobName);
CloudBlockBlob destinationBlob = blobContainer.GetBlockBlobReference(destBlobName);
//Setup data transfer
TransferContext context = new TransferContext();
Progress<TransferProgress> progress = new Progress<TransferProgress>(
(transferProgress) => {
Console.WriteLine("Bytes uploaded: {0}", transferProgress.BytesTransferred);
});
context.ProgressHandler = progress;
// Start the transfer
try
{
TransferManager.CopyAsync(sourceBlob, destinationBlob,
false /* isServiceCopy */,
null /* options */, context);
}
catch (Exception e)
{
Console.WriteLine("The transfer is cancelled: {0}", e.Message);
}
Console.WriteLine("CloudBlob {0} is copied to {1} ====successfully====",
sourceBlob.Uri.ToString(),
destinationBlob.Uri.ToString());
Console.ReadLine();
}
}
}
Note that "Azure Storage Data Movement Library" is very robust so you can track the transfer progress, cancel the operation or even suspend it to resume it later ;)
One of the easiest ways to copy files is with the AzCopy utility.
I would like to recommend another method other than the above to get this done.
That is azure functions. (serverless compute service).
As a prerequisite, you should have some knowledge in azure functions, creating them, deploying them. 1. What is azure function 2. create an Azure function app
And the following code snippet is the simplest and basic way to perform this action. (In here, when a user uploading a new file to the "demo" blob, the function will be triggered and read that uploaded file from the demo blob and copy to the "output" blob.)
namespace Company.Function{
public static class NamalFirstBlobTrigger
{
[FunctionName("NamalFirstBlobTrigger")]
public static void Run([BlobTrigger("demo/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob,
[Blob("output/testing.cs",FileAccess.Write, Connection = "AzureWebJobsStorage")]Stream outputBlob,
string name,
ILogger log)
{
myBlob.CopyTo(outputBlob);
}
}}

Resources