diff --git a/docs/fsharp/using-fsharp-on-azure/file-storage.md b/docs/fsharp/using-fsharp-on-azure/file-storage.md index 0fa4e8a70e5b5..ce701d46e7c9b 100644 --- a/docs/fsharp/using-fsharp-on-azure/file-storage.md +++ b/docs/fsharp/using-fsharp-on-azure/file-storage.md @@ -26,7 +26,7 @@ Next, use a [package manager](package-management.md) such as [Paket](https://fsp Add the following `open` statements to the top of the `files.fsx` file: -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L1-L5)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L1-L8)] ### Get your connection string @@ -34,29 +34,21 @@ You'll need an Azure Storage connection string for this tutorial. For more infor For the tutorial, you'll enter your connection string in your script, like this: -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L11-L11)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L14-L14)] However, this is **not recommended** for real projects. Your storage account key is similar to the root password for your storage account. Always be careful to protect your storage account key. Avoid distributing it to other users, hard-coding it, or saving it in a plain-text file that is accessible to others. You can regenerate your key using the Azure portal if you believe it may have been compromised. For real applications, the best way to maintain your storage connection string is in a configuration file. To fetch the connection string from a configuration file, you can do this: -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L13-L15)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L16-L18)] Using Azure Configuration Manager is optional. You can also use an API such as the .NET Framework's `ConfigurationManager` type. -### Parse the connection string - -To parse the connection string, use: - -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L21-L22)] - -This will return a `CloudStorageAccount`. - ### Create the File service client -The `CloudFileClient` type enables you to programmatically use files stored in File storage. Here's one way to create the service client: +The `ShareClient` type enables you to programmatically use files stored in File storage. Here's one way to create the service client: -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L28-L28)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L25-L25)] Now you are ready to write code that reads data from and writes data to File storage. @@ -64,39 +56,39 @@ Now you are ready to write code that reads data from and writes data to File sto This example shows how to create a file share if it does not already exist: -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L34-L35)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L31-L31)] -## Create a root directory and a subdirectory +## Create a directory -Here, you get the root directory and get a subdirectory of the root. You create both if they don't already exist. +Here, you get the directory. You create if it doesn't already exist. -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L41-L43)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L37-L41)] -## Upload text as a file +## Upload a file to the sample directory -This example shows how to upload text as a file. +This example shows how to upload a file to the sample directory. -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L49-L50)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L47-L52)] -### Download a file to a local copy of the file +### Download a file to a local file Here you download the file just created, appending the contents to a local file. -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L56-L56)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L58-L60)] ### Set the maximum size for a file share -The example below shows how to check the current usage for a share and how to set the quota for the share. `FetchAttributes` must be called to populate a share's `Properties`, and `SetProperties` to propagate local changes to Azure File Storage. +The example below shows how to check the current usage for a share and how to set the quota for the share. -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L62-L72)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L66-L75)] ### Generate a shared access signature for a file or file share -You can generate a shared access signature (SAS) for a file share or for an individual file. You can also create a shared access policy on a file share to manage shared access signatures. Creating a shared access policy is recommended, as it provides a means of revoking the SAS if it should be compromised. +You can generate a shared access signature (SAS) for a file share or for an individual file. You can also create a shared access policy on a file share to manage shared access signatures. Creating a shared access permissions is recommended, as it provides a means of revoking the SAS if it should be compromised. -Here, you create a shared access policy on a share, and then use that policy to provide the constraints for a SAS on a file in the share. +Here, you create a shared access permissions on a share, and then set that permissions to provide the constraints for a SAS on a file in the share. -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L78-L94)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L81-L101)] For more information about creating and using shared access signatures, see [Using Shared Access Signatures (SAS)](/azure/storage/storage-dotnet-shared-access-signature-part-1) and [Create and use a SAS with Blob storage](/azure/storage/storage-dotnet-shared-access-signature-part-2). @@ -108,13 +100,13 @@ You can copy a file to another file or to a blob, or a blob to a file. If you ar Here, you copy a file to another file in the same share. Because this copy operation copies between files in the same storage account, you can use Shared Key authentication to perform the copy. -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L100-L101)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L106-L108)] ### Copy a file to a blob Here, you create a file and copy it to a blob within the same storage account. You create a SAS for the source file, which the service uses to authenticate access to the source file during the copy operation. -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L107-L120)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L114-L131)] You can copy a blob to a file in the same way. If the source object is a blob, then create a SAS to authenticate access to that blob during the copy operation. @@ -124,7 +116,7 @@ Azure Storage Analytics supports metrics for File storage. With metrics data, yo You can enable metrics for File storage from the [Azure portal](https://portal.azure.com), or you can do it from F# like this: -[!code-fsharp[FileStorage](~/samples/snippets/fsharp/azure/file-storage.fsx#L126-L140)] +[!code-fsharp[FileStorage](../../../samples/snippets/fsharp/azure/file-storage.fsx#L137-L155)] ## Next steps diff --git a/samples/snippets/fsharp/azure/file-storage.fsx b/samples/snippets/fsharp/azure/file-storage.fsx index 573a48bb9b0d0..3b55ae428483a 100644 --- a/samples/snippets/fsharp/azure/file-storage.fsx +++ b/samples/snippets/fsharp/azure/file-storage.fsx @@ -1,8 +1,11 @@ open System open System.IO -open Microsoft.Azure // Namespace for CloudConfigurationManager -open Microsoft.Azure.Storage // Namespace for CloudStorageAccount -open Microsoft.Azure.Storage.File // Namespace for File storage types +open Azure +open Azure.Storage // Namespace for StorageSharedKeyCredential +open Azure.Storage.Blobs // Namespace for BlobContainerClient +open Azure.Storage.Sas // Namespace for ShareSasBuilder +open Azure.Storage.Files.Shares // Namespace for File storage types +open Azure.Storage.Files.Shares.Models // Namespace for ShareServiceProperties // // Get your connection string. @@ -14,127 +17,139 @@ let storageConnString = "..." // fill this in from your storage account let storageConnString = CloudConfigurationManager.GetSetting("StorageConnectionString") *) -// -// Parse the connection string. -// - -// Parse the connection string and return a reference to the storage account. -let storageAccount = CloudStorageAccount.Parse(storageConnString) // // Create the File service client. // -let fileClient = storageAccount.CreateCloudFileClient() +let share = ShareClient(storageConnString, "shareName") // // Create a file share. // -let share = fileClient.GetShareReference("myfiles") -share.CreateIfNotExists() +share.CreateIfNotExistsAsync() // -// Create a root directory and a subdirectory +// Create a directory // -let rootDir = share.GetRootDirectoryReference() -let subDir = rootDir.GetDirectoryReference("myLogs") -subDir.CreateIfNotExists() +// Get a reference to the directory +let directory = share.GetDirectoryClient("directoryName") + +// Create the directory if it doesn't already exist +directory.CreateIfNotExistsAsync() // -// Upload a file to a subdirectory +// Upload a file to the sample directory // -let file = subDir.GetFileReference("log.txt") -file.UploadText("This is the content of the log file") +let file = directory.GetFileClient("fileName") +let stream = File.OpenRead("localFilePath") +file.Create(stream.Length) +file.UploadRange( + HttpRange(0L, stream.Length), + stream) // -// Download a file to a local fie +// Download a file to a local file // -file.DownloadToFile("log.txt", FileMode.Append) +let download = file.Download() +let downStream = File.OpenWrite("Save_Download_Path") +download.Value.Content.CopyTo(stream) // // Set the maximum size for a file share. // // stats.Usage is current usage in GB -let stats = share.GetStats() -share.FetchAttributes() +let ONE_GIBIBYTE = 10_737_420_000L // Number of bytes in 1 gibibyte +let stats = share.GetStatistics().Value +let currentGiB = int (stats.ShareUsageInBytes / ONE_GIBIBYTE) // Set the quota to 10 GB plus current usage -share.Properties.Quota <- stats.Usage + 10 |> Nullable -share.SetProperties() +share.SetQuotaAsync(currentGiB + 10) // Remove the quota -share.Properties.Quota <- Nullable() -share.SetProperties() +share.SetQuotaAsync(0) // // Generate a shared access signature for a file or file share. // -// Create a 24-hour read/write policy. -let policy = - SharedAccessFilePolicy - (SharedAccessExpiryTime = (DateTimeOffset.UtcNow.AddHours(24.) |> Nullable), - Permissions = (SharedAccessFilePermissions.Read ||| SharedAccessFilePermissions.Write)) +let accountName = "..." // Input your storage account name +let accountKey = "..." // Input your storage account key +// Create a 24-hour read/write policy. +let expiration = DateTimeOffset.UtcNow.AddHours(24.) +let fileSAS = ShareSasBuilder( + ShareName = "shareName", + FilePath = "filePath", + Resource = "f", + ExpiresOn = expiration) -// Set the policy on the share. -let permissions = share.GetPermissions() -permissions.SharedAccessPolicies.Add("policyName", policy) -share.SetPermissions(permissions) +// Set the permissions for the SAS +let permissions = ShareFileSasPermissions.All +fileSAS.SetPermissions(permissions) -let sasToken = file.GetSharedAccessSignature(policy) -let sasUri = Uri(file.StorageUri.PrimaryUri.ToString() + sasToken) +// Create a SharedKeyCredential that we can use to sign the SAS token +let credential = StorageSharedKeyCredential(accountName, accountKey) -let fileSas = CloudFile(sasUri) -fileSas.UploadText("This write operation is authenticated via SAS") +// Build a SAS URI +let fileSasUri = UriBuilder($"https://{accountName}.file.core.windows.net/{fileSAS.ShareName}/{fileSAS.FilePath}") +fileSasUri.Query = fileSAS.ToSasQueryParameters(credential).ToString() // // Copy a file to another file. // - -let destFile = subDir.GetFileReference("log_copy.txt") -destFile.StartCopy(file) +let sourceFile = ShareFileClient(storageConnString, "shareName", "sourceFilePath") +let destFile = ShareFileClient(storageConnString, "shareName", "destFilePath") +destFile.StartCopyAsync(sourceFile.Uri) // // Copy a file to a blob. // -// Get a reference to the blob to which the file will be copied. -let blobClient = storageAccount.CreateCloudBlobClient() -let container = blobClient.GetContainerReference("myContainer") -container.CreateIfNotExists() -let destBlob = container.GetBlockBlobReference("log_blob.txt") +// Create a new file SAS +let fileSASCopyToBlob = ShareSasBuilder( + ShareName = "shareName", + FilePath = "sourceFilePath", + Resource = "f", + ExpiresOn = DateTimeOffset.UtcNow.AddHours(24.)) +let permissionsCopyToBlob = ShareFileSasPermissions.Read +fileSASCopyToBlob.SetPermissions(permissionsCopyToBlob) +let fileSasUriCopyToBlob = UriBuilder($"https://{accountName}.file.core.windows.net/{fileSASCopyToBlob.ShareName}/{fileSASCopyToBlob.FilePath}") -let filePolicy = - SharedAccessFilePolicy - (Permissions = SharedAccessFilePermissions.Read, - SharedAccessExpiryTime = (DateTimeOffset.UtcNow.AddHours(24.) |> Nullable)) +// Get a reference to the file. +let sourceFileCopyToBlob = ShareFileClient(fileSasUriCopyToBlob.Uri) -let fileSas2 = file.GetSharedAccessSignature(filePolicy) -let sasUri2 = Uri(file.StorageUri.PrimaryUri.ToString() + fileSas2) -destBlob.StartCopy(sasUri2) +// Get a reference to the blob to which the file will be copied. +let containerCopyToBlob = BlobContainerClient(storageConnString, "containerName"); +containerCopyToBlob.CreateIfNotExists() +let destBlob = containerCopyToBlob.GetBlobClient("blobName") +destBlob.StartCopyFromUriAsync(sourceFileCopyToBlob.Uri) // // Troubleshooting File storage using metrics. // -open Microsoft.Azure.Storage.File.Protocol -open Microsoft.Azure.Storage.Shared.Protocol +// Instatiate a ShareServiceClient +let shareService = ShareServiceClient(storageConnString); + +// Set metrics properties for File service +let props = ShareServiceProperties() + +props.HourMetrics = ShareMetrics( + Enabled = true, + IncludeApis = true, + Version = "1.0", + RetentionPolicy = ShareRetentionPolicy(Enabled = true,Days = 14)) -let props = - FileServiceProperties( - (HourMetrics = MetricsProperties( - MetricsLevel = MetricsLevel.ServiceAndApi, - RetentionDays = (14 |> Nullable), - Version = "1.0"), - MinuteMetrics = MetricsProperties( - MetricsLevel = MetricsLevel.ServiceAndApi, - RetentionDays = (7 |> Nullable), - Version = "1.0")) +props.MinuteMetrics = ShareMetrics( + Enabled = true, + IncludeApis = true, + Version = "1.0", + RetentionPolicy = ShareRetentionPolicy(Enabled = true,Days = 7)) -fileClient.SetServiceProperties(props) +shareService.SetPropertiesAsync(props)