Trouble getting a file from Azure container - azure-storage

I am trying to get a file from Azure container. I need to read its content.
The file has been uploaded to umbraco media, media are stored in our Azure container.
Its normal (umbraco) url would be like:
~/media/10890/filename.xls
I am trying to retrieve it like this:
var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["strorageconnstring"]);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("storagemedia");
The thing is - I am not sure how I am supposed to retrieve a particular file? I tried:
1.
CloudBlobDirectory dira = container.GetDirectoryReference("10890"); // file folder within media
var list = dira2.ListBlobs(useFlatBlobListing: true).ToList(); // Returns error saying "The requested URI does not represent any resource on the server."
However the 10890 folder within media storage exists and I can browse it with storage browser.
2.
CloudBlockBlob blobFile = container.GetBlockBlobReference("10890/filename.xls");
string text;
using (var memoryStream = new MemoryStream())
{
blobFile.DownloadToStream(memoryStream); // Throws "The specifed resource name contains invalid characters." error
var length = memoryStream.Length;
text = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
}
Any idea how to read the file? And what am I doing wrong?

Thank You Gaurav for providing your suggestion in comment section.
Thank You nicornotto for confirming that your issue got resolved by changing the container name reference in the below statement.
var container = blobClient.GetContainerReference("storagemedia");

Related

Easy way to retrieve image source in abp

I'm pretty new to ABP Framework and probably this question has a really simple answer, but I haven't managed to find it. Images are an important part of any app and handling them the best way (size, caching) is mandatory.
Scenario
setup a File System Blob Storing provider. This means that the upload file will be stored in the file system as an image file
make a service that uses a Blob container to save and retrieve the image. So, after saving it, I use the unique file name as a blob name. This name is used to retrieve it back.
the user is logged in, so authorization is required
I can easily obtain the byte[]s of the image by calling blobContainer.GetAllBytesOrNullAsync(blobName)
I want to easily display the image in <img> or in datatable row directly.
So, here is my question: is there an easy way to use a blob stored image as src of a <img> directly in a razor page? What I've managed to achieve is setting in the model, a source as a string made from image type + bytes converted to base 64 string (as here) however in this case I need to do it in the model and also I don't know if caching is used by the browser. I don't see how caching would work in this case.
I am aware that this may be a question more related to asp.net core, but I was thinking that maybe in abp there is some way via a link to access the image.
If you have the ID of the blob then it is easy to do. Just create a Endpoint to get the Image based on the blob id.
Here is the sample AppService
public class DocumentAppService : FileUploadAppService
{
private readonly IBlobContainer<DocumentContainer> _blobContainer;
private readonly IRepository<Document, Guid> _repository;
public DocumentAppService(IRepository<Document, Guid> repository, IBlobContainer<DocumentContainer> blobContainer)
{
_repository = repository;
_blobContainer = blobContainer;
}
public async Task<List<DocumentDto>> Upload([FromForm] List<IFormFile> files)
{
var output = new List<DocumentDto>();
foreach (var file in files)
{
using var memoryStream = new MemoryStream();
await file.CopyToAsync(memoryStream).ConfigureAwait(false);
var id = Guid.NewGuid();
var newFile = new Document(id, file.Length, file.ContentType, CurrentTenant.Id);
var created = await _repository.InsertAsync(newFile);
await _blobContainer.SaveAsync(id.ToString(), memoryStream.ToArray()).ConfigureAwait(false);
output.Add(ObjectMapper.Map<Document, DocumentDto>(newFile));
}
return output;
}
public async Task<FileResult> Get(Guid id)
{
var currentFile = _repository.FirstOrDefault(x => x.Id == id);
if (currentFile != null)
{
var myfile = await _blobContainer.GetAllBytesOrNullAsync(id.ToString());
return new FileContentResult(myfile, currentFile.MimeType);
}
throw new FileNotFoundException();
}
}
Upload function will upload the files and Get function will get the file.
Now set the Get route as a src for the image.
Here is the blog post: https://blog.antosubash.com/posts/dotnet-file-upload-with-abp
Repo: https://github.com/antosubash/FileUpload

set blob properties return an error

I want to set cache control property of all uploaded blobs before, but it throws exception "The remote server returned an error: (404) Not Found."
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
List<CloudBlobContainer> containers = blobClient.ListContainers().ToList();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
List<IListBlobItem> blobs = container.ListBlobs().ToList();
int count = 0;
foreach (IListBlobItem blob in blobs)
{
CloudBlockBlob b = container.GetBlockBlobReference(blob.Uri.ToString());
b.Properties.CacheControl = "public, max-age=1296000";
b.SetProperties();
Console.WriteLine("cached"+count.ToString());
count++;
}
The error is being thrown at SetProperties.
You are doing a hierarchical listing, which can return virtual directories as well as blobs. For example, if you have a blob named "foo/bar" then your listing will return a CloudBlobDirectory named "foo/". When you try to use this as a blob name, the service retruns 404 because the blob does not exist.
To accomplish what you want, pass "useFlatBlobListing: true" to the call to ListBlobs and then cast each returned IListBlobItem to CloudBlob.

Upload a file to Azure Blobservice from a public URI

Is Microsoft planning on to create a method in Azure BlobService that fetches data to the storage from a public URI? Quick google search shows it had something similar in the past, but API is outdated now.
Please have a try to use CloudBlockBlob.StartCopy or CloudBlockBlob.StartCopyAsync,it can work correctly. I write a demo for it.More info about the CloudBlockBlob.StartCopy please refer to the article.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse("Storage connection string");
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("newcontainer"); //container name
var source = new Uri("public file url");
CloudBlockBlob target = container.GetBlockBlobReference("targe blob name");
target.StartCopy(source);
//or target.StartCopyAsync(source).Wait();
Update:
I did a test with copy blob api, detail info please refer to the screenshot.

Can you download a specific Block from an Azure Block Blob?

Is it possible to download a specific block from an Azure Block Blob if you know the Block Id?
Yes, you absolutely can, here's an example of how to download the first block:
var storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=...;AccountKey=...;EndpointSuffix=core.windows.net");
CloudBlobClient serviceClient = storageAccount.CreateCloudBlobClient();
var container = serviceClient.GetContainerReference("containerName");
var blockBlob = container.GetBlockBlobReference("blobName");
var blocklist = await blockBlob.DownloadBlockListAsync();
var firstBlock = blocklist.First();
var memStream = new MemoryStream();
await blockBlob.DownloadRangeToStreamAsync(memStream, 0, firstBlock.Length);
string contents;
using (var streamReader = new StreamReader(memStream))
{
contents = await streamReader.ReadToEndAsync();
}
You will need a couple of packages from nuget:
Microsoft.WindowsAzure.Storage
Microsoft.WindowsAzure.Storage.Blob
You could leverage Microsoft Azure Storage SDK for getting started with Azure Blob Storage quickly. And the Azure Storage SDK is a wrapper of Blob Service REST API. From the official tutorial about Blob Service REST API, we couldn't find anything about downloading the specific block via the Block Id. In addition, you could use Get Blob to download the bytes of your blob in the specified range by specifying the offset and the length of data to download from your blob.

Cannot get file name when upload file in google app script

I want to get file name when upload file finish. I have this example and follow this code.
However, when I get file name from following code:
var fileBlob = e.parameter.thefile;
The result is always return string "FileUpload".
How can I get the file name? Thank you so much.
You can get the name of the file by using the following code.
var fileBlob = e.parameter.thefile;
fileBlob.getName();
You can get the name of the file without storing in Drive through this.
Since fileBlob is of type blob we are getting through e.parameter.name, we have to refer Class Blob for that.
For further methods supported by Class Blob refer to
Class Blob.
The example script you were following produces a DocsList File object. This object has a method getName() so to extend the function in the example…
function doPost(e) {
// data returned is a blob for FileUpload widget
var fileBlob = e.parameter.thefile;
var doc = DocsList.createFile(fileBlob);
var fileName = doc.getName();
}
give that a whirl.