Showing posts with label Stream. Show all posts
Showing posts with label Stream. Show all posts

Sunday, 13 September 2020

Upload and Retrieve File from Azure Blob Storage in C# & VB for .NET Framework

Azure Blob Storage is one of the Microsoft Azure Resource to store any types of file. Files that are placed in the blob storage can be accessible through API, Microsoft Azure Storage Explorer, directly from the azure portal or from PowerShell. So if you have the need to archive files or share the access to the file to different environment or application that is located in different locations, then Blob Storage is a good candidate for you. For more detail, you may further check it out from this link https://docs.microsoft.com/en-us/azure/storage/common/storage-introduction#blob-storage.

So to get started on how to access Blob Storage from your code, firstly you need to retrieve the following packages from NuGet.

Microsoft.Azure.ConfigurationManager
Microsoft.Azure.KeyVault.Core
Microsoft.Azure.Storage.Blob
Microsoft.Azure.Storage.Common
Newtonsoft.Json

Once you have gotten the necessary packages, you need to define where is your blob storage located in your configuration file. But if you currently do not have an azure account, you may setup and run the Microsoft Azure Storage Emulator on your machine. Refer to this link https://docs.microsoft.com/en-us/azure/storage/common/storage-use-emulator for more information on how to set it up.

If you are using the Microsoft Azure Storage Emulator, define the following setting in the configuration file.

<add key="StorageConnectionString" value="UseDevelopmentStorage=true" />

Otherwise, you need to retrieve the connection string from the Azure Portal. The format of the connection string is as follows.

<add key="StorageConnectionString" value="DefaultEndpointsProtocol=https;AccountName=YourAzureBlobStorageName;AccountKey=YourAzureBlobStorageKey" />

To start using the packages retrieved from NuGet. Define the CloudStorageAccount instance based on the configuration defined above. This is to specify the location of the Azure Blob Storage.

[C#]
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"));

[VB]
Dim cloudStorageAccount As CloudStorageAccount = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString"))

With the CloudStorageAccount, use it to create the container. This is required before file can be placed into the Azure Blob Storage. Do take note that the container name must be lower case. For more detail about the container, you may check the following link https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction#blob-storage-resources.

[C#]
CloudBlobContainer cloudBlobContainer = cloudStorageAccount.CreateCloudBlobClient().GetContainerReference("containername");

cloudBlobContainer.CreateIfNotExists();

[VB]
Dim cloudBlobContainer As CloudBlobContainer = cloudStorageAccount.CreateCloudBlobClient().GetContainerReference("containername")

cloudBlobContainer.CreateIfNotExists()

After the creation of the container, it is now possible to upload file to the Azure Blob Storage. In the following demonstration, the file in the local machine will be used to upload.

[C#]
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference("SampleFileInBlob.txt");

cloudBlockBlob.UploadFromFile(Path.Combine(Environment.CurrentDirectory, "SampleFile.txt"));

[VB]
Dim cloudBlockBlob As CloudBlockBlob = cloudBlobContainer.GetBlockBlobReference("SampleFileInBlob.txt")

cloudBlockBlob.UploadFromFile(Path.Combine(Environment.CurrentDirectory, "SampleFile.txt"))

Alternatively, the following demonstrate on how to retrieve the file from Azure Blob Storage and save it on local machine. 

[C#]
CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference("SampleFileInBlob.txt");

cloudBlockBlob.DownloadToFile(Path.Combine(Environment.CurrentDirectory, "SavedSampleFile.txt"), FileMode.Create);

[VB]
Dim cloudBlockBlob As CloudBlockBlob = cloudBlobContainer.GetBlockBlobReference("SampleFileInBlob.txt")

cloudBlockBlob.DownloadToFile(Path.Combine(Environment.CurrentDirectory, "SavedSampleFile.txt"), FileMode.Create)

Check out the sample code here https://1drv.ms/u/s!Aj2AA7hoIWHm03MBsAUCRtvATCYe.




Sunday, 26 June 2016

Send and Download File with WCF Stream in C# & VB

Ever faced a situation where you need to send or receive file through WCF but somehow the file gets corrupted when downloading through byte array or when sending large file in byte array causing your application to used up very high memory. To solve this, you may want to consider implementing WCF Stream. You may refer to the following link for more detail about WCF Stream https://msdn.microsoft.com/en-us/library/ms751463(v=vs.110).aspx.

To get started, implement services and contracts for sending and receiving file in stream through WCF. For the service to send or return more than 1 parameter together with Stream class, you need to implement MessageContract instead of DataContract. For more detail about MessageContract, refer to this link https://msdn.microsoft.com/en-us/library/ms730255(v=vs.110).aspx.

[C#]
[MessageContract]
public class DownloadFileResponse
{
    [MessageHeader]
    public string FileName { get; set; }

    [MessageBodyMember]
    public Stream Stream { get; set; }
}

[MessageContract]
public class SaveFileRequest
{
    [MessageHeader]
    public string FileName { get; set; }

    [MessageBodyMember]
    public Stream Stream { get; set; }

}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class FileService : IFileService
{
    public void SaveFile(SaveFileRequest saveFileRequest)
    {
        // Do your stuff
    }

    public DownloadFileResponse DownloadFile()
    {
        // Do your stuff
    }
}

[ServiceContract]
public interface IFileService
{
    [OperationContract]
    void SaveFile(SaveFileRequest saveFileRequest);

    [OperationContract]
    DownloadFileResponse DownloadFile();
}

[VB]
<MessageContract>
Public Class DownloadFileResponse
    <MessageHeader>
    Private _fileName As String
    Public Property FileName() As String
        Get
            Return _fileName
        End Get
        Set(ByVal value As String)
            _fileName = value
        End Set
    End Property

    <MessageBodyMember>
    Private _stream As Stream
    Public Property Stream() As Stream
        Get
            Return _stream
        End Get
        Set(ByVal value As Stream)
            _stream = value
        End Set
    End Property
End Class

<MessageContract>
Public Class SaveFileRequest
    <MessageHeader>
    Private _fileName As String
    Public Property FileName() As String
        Get
            Return _fileName
        End Get
        Set(ByVal value As String)
            _fileName = value
        End Set
    End Property

    <MessageBodyMember>
    Private _stream As Stream
    Public Property Stream() As Stream
        Get
            Return _stream
        End Get
        Set(ByVal value As Stream)
            _stream = value
        End Set
    End Property
End Class

<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerCall, ConcurrencyMode:=ConcurrencyMode.Single)>
Public Class FileService
    Implements IFileService

    Public Sub SaveFile(ByVal saveFileRequest As SaveFileRequest) Implements IFileService.SaveFile
        ' Do your stuff
    End Sub

    Public Function DownloadFile() As DownloadFileResponse Implements IFileService.DownloadFile
        ' Do your stuff
    End Function
End Class

<ServiceContract>
Public Interface IFileService
    <OperationContract>
    Sub SaveFile(ByVal saveFileRequest As SaveFileRequest)

    <OperationContract>
    Function DownloadFile() As DownloadFileResponse
End Interface

Do take note that when retrieving the stream from a physical file through File class, make sure to close and dispose the File class after moved the content into a stream to prevent the file being locked by your application.

There are few things you can configure in web configuration file. To send or receive file in stream, change the attribute "transferMode" to "Streamed" in binding element. By default, "transferMode" is "buffered", what this mean is WCF will hold the content in memory until the file is transferred, in which will lead to very high memory usage if transferring a large file. For more details about "transferMode" attribute, you may refer here https://msdn.microsoft.com/en-us/library/system.servicemodel.transfermode(v=vs.110).aspx

The second attribute that you can configured is "maxReceivedMessageSize". This attribute is for your application to receive large file send from another application through WCF. Refer here https://msdn.microsoft.com/en-us/library/ms731361(v=vs.110).aspx if you want to know what else can you configured in binding element.

[web.config]
<bindings>
  <basicHttpBinding>
    <binding name="basicHttp"
             transferMode="Streamed"
             maxReceivedMessageSize="2147483647"></binding>
  </basicHttpBinding>
</bindings>

Make sure to assign the binding that you have configured to your service, otherwise it will not take effect. To assign the binding, set your binding name to the attribute "bindingConfiguration" under endpoint element.

[web.config]
<services>
  <service name="WCFSDemoVB.Services.FileService"
           behaviorConfiguration="DefaultServiceBehavior">
    <endpoint name="basicHttpFileService"
              address=""
              binding="basicHttpBinding"
              bindingConfiguration="basicHttp"
              contract="WCFSDemoVB.Services.Contracts.IFileService" />
    <endpoint address="mex"
              binding="mexHttpBinding"
              contract="IMetadataExchange" />
  </service>
</services>

Once done, you can now create a client application to send or receive file with stream through the WCF service that you have implemented. 

The following samples are developed in layered based on http://serena-yeoh.blogspot.com/2014/03/layered-architecture-solution-guidance.html: C#: https://1drv.ms/u/s!Aj2AA7hoIWHmgmw_UVGt9PBYtaeR
VB: https://1drv.ms/u/s!Aj2AA7hoIWHmgmsNk_zKLGQj4YyB