I have a requirement where i want to read blob and to upload in Sftp location.Blob path is available as in the format "/container/folder1/subfold1/abc.blob".I am using below code to read the blob from above blob path
BlobServiceClient blobServiceClient1 = new BlobServiceClient(connectionString);
BlobContainerClient containerClient1 = blobServiceClient1.GetBlobContainerClient(containerName);
var bname = "container/folder1/subfold1/abc.blob";
var blockBlobClient1 = containerClient1.GetBlockBlobClient(bname);
using (var uploadBlobStream = blockBlobClient1 .OpenReadAsync())
{
_sftp.Connect();
var blobPath = string.Format("{0}/{1}", remoteFilePath, "tst.txt");
_sftp.UploadFile(uploadBlobStream.Result, remoteFilePath, true);
_sftp.Disconnect();
}
But it throws error that Blob file is not present. Can anyone help on this.
You can try the following changes:
You will need to use the value of containerName instead of "container" in the path.
var bname = $"{containerName}/folder1/subfold1/abc.blob";
The OpenReadAsync method returns a Task object that represents the asynchronous operation, rather than the stream itself. You will need to await the task to get the stream, like this:
using (var uploadBlobStream = await blockBlobClient1.OpenReadAsync())
{
// ...
}
Also, it's worth noting that the UploadFile method expects a Stream object as its first argument, but you are passing it the Task object returned by OpenReadAsync. You will need to pass the stream itself, like this:
_sftp.UploadFile(uploadBlobStream, remoteFilePath, true);
Do upvote, if you found this useful. Thanks :)
Related
I am trying to upload a new append blob file to a container every time a message comes in from a service bus. I do not want to append to the blob that is already there. I want to create a whole new append blob and add it at the end.
Is this possible?
I was looking at this article but couldn't quiet understand what they meant when they got to the content part: https://azuresdkdocs.blob.core.windows.net/$web/javascript/azure-storage-blob/12.1.1/classes/appendblobclient.html#appendblock
Here is the code that I have so far:
public static async void StoreToBlob(Services service)
{
//Serealize Object
var sender = JsonConvert.SerializeObject(service);
// Create a BlobServiceClient object which will be used to create a container client
BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);
// Create the container and return a container client object
BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);
// Create the container if it doesn't already exist.
await containerClient.CreateIfNotExistsAsync();
//Reference to blob
AppendBlobClient appendBlobClient = containerClient.GetAppendBlobClient("services" + Guid.NewGuid().ToString() + ".json");
// Create the blob.
appendBlobClient.Create();
await appendBlobClient.AppendBlock(sender, sender.Length); //here is where I am having an issue
}
Can you try something like the following (not tested code):
byte[] blockContent = Encoding.UTF8.GetBytes(sender);
using (var ms = new MemoryStream(blockContent))
{
appendBlobClient.AppendBlock(ms, blockContent.Length);
}
Essentially we're converting the string to byte array, creating a stream out of it and then uploading that stream.
i am trying to download the word document stored in azure blob container having private access and i need to convert downloaded document into byte array so that i can be able to send to react app
this is the code i am trying below
[Authorize, HttpGet("{id}/{projectphase?}")]
public async Task<ActionResult<DesignProject>> GetDesignProject(string id, string projectphase = null)
{
var blobContainerName = Startup.Configuration["AzureStorage:BlobContainerName"];
var azureStorageConnectionString = Startup.Configuration["AzureStorage:ConnectionString"];
BlobContainerClient blobContainerClient = new BlobContainerClient(azureStorageConnectionString, blobContainerName);
blobContainerClient.CreateIfNotExists();
....... // not sure how to proceed further
.......
......
return new InlineFileContentResult('here i need to return byte array???', "application/docx") { FileDownloadName = fileName };
}
I have got the full path name where the file has been stored like as below
https://xxxx.blob.core.windows.net/design-project-files/99999-99/99999-99-BOD-Concept.docx
and then i have got the file name as well 99999-99-BOD-Concept.docx
Could any one please guide me how to proceed with the next to download the document that would be very grateful to me.
Please try something like the following (untested code though):
public async Task<ActionResult<DesignProject>> GetDesignProject(string id, string projectphase = null)
{
var blobContainerName = Startup.Configuration["AzureStorage:BlobContainerName"];
var azureStorageConnectionString = Startup.Configuration["AzureStorage:ConnectionString"];
BlobContainerClient blobContainerClient = new BlobContainerClient(azureStorageConnectionString, blobContainerName);
blobContainerClient.CreateIfNotExists();
var blobClient = new BlobClient("https://xxxx.blob.core.windows.net/design-project-files/99999-99/99999-99-BOD-Concept.docx");
var blobName = blobClient.Name;
blobClient = new BlobClient(azureStorageConnectionString, blobContainerName, blobName);
using (var ms = new MemoryStream())
{
await blobClient.DownloadToAsync(ms);
return new InlineFileContentResult(ms.ToArray(), "application/docx") { FileDownloadName = fileName };
}
}
Basically what we're doing is that we're first creating a BlobClient using the URL that you have so that we can extract blob's name out of that URL (you can do URL parsing as well). Once we have the blob's name, we create a new instance of BlobClient using connection string, blob container name and blob's name.
Then we download the blob's content as stream and convert that stream to byte array (this part I am not 100% sure that my code would work) and return that byte array.
You don't really need to have this process where your react app requests to your server, so your server downloads the file and then sends it to the react app; that file in blob storage is on the web, downloadable from blob storage so it's kinda unnecessary to hassle your sevrer into being a proxy for it
If you configure public access for blobs then you just put that URL into your react app - user clicks it, bytes download. Happy days. If you have a private container you can still generate SAS URLs for the blobs
If you actually need the bytes in your react app, then just fetch it with a javascript web request - you'll need to set a CORS policy on the blob container though
If you really want to download the file to/via the server, you'll probably have to get into streaming it to the response stream connected to the react app, passed into the SOMETHING below:
BlobClient blob = blobContainerClient.GetBlobClient( BLOB NAME I.E PATH INSIDE CONTAINER);
//download to a file or stream
await blob.DownloadToAsync( SOMETHING );
Problem
I am trying to copy the blob from one directory and past into other directory and the delete the blob from source. I already tried the below code but not copy and past into another folder is done but delete operation works.
Code
var cred = new StorageCredentials("storageName", "Key");
var account = new CloudStorageAccount(cred, true);
var client = account.CreateCloudBlobClient();
var container = client.GetContainerReference("containerName");
CloudBlockBlob sourceBlob = container.GetBlockBlobReference("folder/test.jpg");
//this doesn't work
sourceBlob.StartCopyAsync(new Uri("destination url"));
//this works
sourceBlob.DeleteAsync();
You need to await as Igor mentioned.
StartCopyAsync is just a method to "start" copy process, you still need to monitor the copy state before deleting the blob. Please find my answer here for more details: How to get updated copy state of azure blob when using blob StartCopyAsync
Well, you have to await async methods. StartCopyAsync fails, because you run a delete file call at the same time. Try using await or Result property.
var cred = new StorageCredentials("storageName", "Key");
var account = new CloudStorageAccount(cred, true);
var client = account.CreateCloudBlobClient();
var container = client.GetContainerReference("containerName");
CloudBlockBlob sourceBlob = container.GetBlockBlobReference("folder/test.jpg");
//this doesn't work
await sourceBlob.StartCopyAsync(new Uri("destination url"));
//this works
await sourceBlob.DeleteAsync();
Code not tested, but should give you a general idea.
I am trying to figure out how to take a file from an html form and save it to my Azure Blob storage. I have found many posts about doing this for JavaScript but I am trying to do it via C#. One source I found said to do
using (YourFileUpload.PostedFile.InputStream)
{
blockBlob.UploadFromStream((FileStream)YourFileUpload.PostedFile.InputStream);
}
but PostedFile does not exist in the HttpPostedFileBase object.
The code I have built out so far is
public static int UploadFile(string FileName, HttpPostedFileBase UploadedFile, int ExistingFileID = 0)
{
var StorageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnectionString"].ToString());
var BlobClient = StorageAccount.CreateCloudBlobClient();
var Container = BlobClient.GetContainerReference("ffinfofiles");
var BlobBlock = Container.GetBlockBlobReference(FileName);
var FileExtension = Path.GetExtension(UploadedFile.FileName.ToLower());
using (UploadedFile.InputStream)
{
BlobBlock.UploadFromStream((FileStream)UploadedFile.InputStream);
}
but when I run this I get the error:
Unable to cast object of type 'System.Web.HttpInputStream' to type 'System.IO.FileStream'.
What method do I need to do so I can upload the file to the Azure Blob?
You should not try to cast UploadedFile.InputStream to a FileStream. CloudBlockBlob.UploadFromStream requires a Stream object, so it should be able to work directly with UploadedFile.InputStream.
Is there are any way to replace a file if the same name exists? I can't see any replace method in Azure Storage. Here is my code:
var client = new CloudBlobClient(
new Uri(" http://sweetapp.blob.core.windows.net/"), credentials);
var container = client.GetContainerReference("cakepictures");
await container.CreateIfNotExistsAsync();
var perm = new BlobContainerPermissions();
perm.PublicAccess = BlobContainerPublicAccessType.Blob;
await container.SetPermissionsAsync(perm);
var blockBlob = container.GetBlockBlobReference(newfilename + i + file.FileType);
using (var fileStream = await file.OpenSequentialReadAsync())
{
await blockBlob.UploadFromStreamAsync(fileStream);
}
Is there anything that I could add into this code so that it replaces existing or same file name?
If a blob exists in blob storage and if you upload another file with the same name as that of the blob, old blob contents will automatically be replaced with the contents of new file. You don't have to do anything special.
As Gaurav also mentioned in his answer, the default behavior of UploadFromStream API is to overwrite if the blob already exists.