-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Readme #12972
Readme #12972
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
# Azure Storage Java NIO Blob plugin library for Java | ||
## This README is not yet updated for this project and is a skeleton copied from blobs | ||
# Azure Storage Blob NIO FileSystemProvider | ||
|
||
This package allows you to interact with Azure Blob Storage through the standard Java NIO Filesystem APIs. | ||
|
||
[Source code][source] | [API reference documentation][docs] | [REST API documentation][rest_docs] | [Product documentation][product_docs] | [Samples][samples] | ||
|
||
|
@@ -35,8 +36,8 @@ az storage account create \ | |
|
||
### Authenticate the client | ||
|
||
In order to interact with the Storage Service (Blob, Queue, Message, MessageId, File) you'll need to create an instance of the Service Client class. | ||
To make this possible you'll need the Account SAS (shared access signature) string of the Storage Account. Learn more at [SAS Token][sas_token] | ||
The simplest way to interact with the Storage Service is to create an instance of the [FileSystem][file_system] class using the [FileSystems][file_systems] API. | ||
To make this possible you'll need the Account SAS (shared access signature) string of the Storage Account or a Shared Key. Learn more at [SAS Token][sas_token] and [Shared Key][shared_key] | ||
|
||
#### Get credentials | ||
|
||
|
@@ -76,55 +77,185 @@ b. Alternatively, get the Account SAS Token from the Azure Portal. | |
|
||
##### **Shared Key Credential** | ||
|
||
a. Use Account name and Account key. Account name is your Storage Account name. | ||
Use Account name and Account key. Account name is your Storage Account name. | ||
|
||
1. Go to your Storage Account | ||
2. Select `Access keys` from the menu on the left | ||
3. Under `key1`/`key2` copy the contents of the `Key` field | ||
|
||
or | ||
## Key concepts | ||
|
||
b. Use the connection string. | ||
NIO on top of Blob Storage is designed for: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nicely written |
||
|
||
- Working with Blob Storage as though it were a local file system | ||
- Random access reads on large blobs without downloading the entire blob | ||
- Uploading full files as blobs | ||
- Creating and navigating a directory structure within an account | ||
- Reading and setting attributes on blobs | ||
|
||
## Design Notes | ||
It is important to recognize that Azure Blob Storage is not a true FileSystem, nor is it the goal of this project to | ||
force Azure Blob Storage to act like a full-fledged FileSystem. While providing FileSystem APIs on top of Azure Blob | ||
Storage can offer convenience and ease of access in certain cases, trying to force the Storage service to work in | ||
scenarios it is not designed for is bound to introduce performance and stability problems. | ||
|
||
To that end, this project will only offer APIs that can be sensibly and cleanly built on top of Azure Blob Storage APIs. | ||
We recognize that this will leave some scenarios unsupported indefinitely, but we would rather offer a product that | ||
works predictably and reliably in its well defined scenarios than eagerly support all possible scenarios at the expense | ||
of quality. Even still, supporting some fundamentally required use cases, such as directories, can result in unexpected | ||
behavior due to the difference between blob storage and a file system. The javadocs on each type and method should | ||
therefore be read and understood for ways in which they may diverge from the standard specified by the JDK. | ||
|
||
Moreover, even from within a given application, it should be remembered that using a remote FileSystem introduces higher | ||
latency. Because of this, particular care must be taken when managing concurrency. Race conditions are more likely to | ||
manifest, network failures occur more frequently than disk failures, and other such distributed application scenarios | ||
must be considered when working with this FileSystem. While the AzureFileSystem will ensure it takes appropriate steps | ||
towards robustness and reliability, the application developer must also design around these failure scenarios and have | ||
fallback and retry options available. | ||
|
||
The view of the FileSystem from within an instance of the JVM will be consistent, but the AzureFileSystem makes no | ||
guarantees on behavior or state should other processes operate on the same data. The AzureFileSystem will assume that it | ||
has exclusive access to the resources stored in Azure Blob Storage and will behave without regard for potential | ||
interfering applications | ||
|
||
Finally, this implementation has currently chosen to always read/write directly to/from Azure Storage without a local | ||
cache. Our team has determined that with the tradeoffs of complexity, correctness, safety, performance, debuggability, | ||
etc. one option is not inherently better than the other and that this choice most directly addresses the current known | ||
use cases for this project. While this has consequences for every API, of particular note is the limitations on writing | ||
data. Data may only be written as an entire file (i.e. random IO or appends are not supported), and data is not | ||
committed or available to be read until the write stream is closed. | ||
|
||
1. Go to your Storage Account | ||
2. Select `Access keys` from the menu on the left | ||
3. Under `key1`/`key2` copy the contents of the `Connection string` field | ||
## Examples | ||
|
||
## Key concepts | ||
The following sections provide several code snippets covering some of the most common Azure Storage Blob NIO tasks, including: | ||
|
||
Blob Storage is designed for: | ||
- [Create a `FileSystem`](#create-a-filesystem) | ||
- [Create a directory](#create-a-directory) | ||
- [Iterate over directory contents](#iterate-over-directory-contents) | ||
- [Read a file](#read-a-file) | ||
- [Write to a file](#write-to-a-file) | ||
- [Copy a file](#copy-a-file) | ||
- [Delete a file](#delete-a-file) | ||
- [Read attributes on a file](#read-attributes-on-a-file) | ||
- [Write attributes to a file](#write-attributes-to-a-file) | ||
|
||
- Serving images or documents directly to a browser | ||
- Storing files for distributed access | ||
- Streaming video and audio | ||
- Writing to log files | ||
- Storing data for backup and restore, disaster recovery, and archiving | ||
- Storing data for analysis by an on-premises or Azure-hosted service | ||
### Create a `FileSystem` | ||
|
||
## Examples | ||
Create a `FileSystem` using the [`shared key`](#get-credentials) retrieved above. | ||
|
||
The following sections provide several code snippets covering some of the most common Azure Storage Blob tasks, including: | ||
Note that you can further configure the file system using constants available in `AzureFileSystem`. | ||
Please see the docs for `AzureFileSystemProvider` for a full explanation of initializing and configuring a filesystem | ||
|
||
- [Create a `BlobServiceClient`](#create-a-blobserviceclient) | ||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L39-L42 --> | ||
```java | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be a way to make a file and add all these snippets in it to catch any errors. Let me go find a PR where I did that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
Map<String, Object> config = new HashMap<>(); | ||
config.put(AzureFileSystem.AZURE_STORAGE_ACCOUNT_KEY, "<your_account_key>"); | ||
config.put(AzureFileSystem.AZURE_STORAGE_FILE_STORES, "<container_names>"); | ||
FileSystem myFs = FileSystems.newFileSystem(new URI("azb://?account=<your_account_name"), config); | ||
``` | ||
|
||
### Create a directory | ||
|
||
Create a directory using the `Files` api | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L46-L47 --> | ||
```java | ||
Path dirPath = myFs.getPath("dir"); | ||
Files.createDirectory(dirPath); | ||
``` | ||
|
||
### Create a `BlobServiceClient` | ||
### Iterate over directory contents | ||
|
||
Create a `BlobServiceClient` using the [`sasToken`](#get-credentials) generated above. | ||
Iterate over a directory using a `DirectoryStream` | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L51-L53 --> | ||
```java | ||
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder() | ||
.endpoint("<your-storage-blob-url>") | ||
.sasToken("<your-sasToken>") | ||
.buildClient(); | ||
for (Path p : Files.newDirectoryStream(dirPath)) { | ||
System.out.println(p.toString()); | ||
} | ||
``` | ||
|
||
### Read a file | ||
|
||
Read the contents of a file using an `InputStream`. Skipping, marking, and resetting are all supported. | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L57-L60 --> | ||
```java | ||
Path filePath = myFs.getPath("file"); | ||
InputStream is = Files.newInputStream(filePath); | ||
is.read(); | ||
is.close(); | ||
``` | ||
|
||
### Write to a file | ||
|
||
Write to a file. Only writing whole files is supported. Random IO is not supported. The stream must be closed in order | ||
to guarantee that the data is available to be read. | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L64-L66 --> | ||
```java | ||
OutputStream os = Files.newOutputStream(filePath); | ||
os.write(0); | ||
os.close(); | ||
``` | ||
|
||
### Copy a file | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L70-L71 --> | ||
```java | ||
Path destinationPath = myFs.getPath("destinationFile"); | ||
Files.copy(filePath, destinationPath, StandardCopyOption.COPY_ATTRIBUTES); | ||
``` | ||
|
||
### Delete a file | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L75-L75 --> | ||
```java | ||
Files.delete(filePath); | ||
``` | ||
|
||
### Read attributes on a file | ||
|
||
Read attributes of a file through the `AzureBlobFileAttributes`. | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L79-L80 --> | ||
```java | ||
AzureBlobFileAttributes attr = Files.readAttributes(filePath, AzureBlobFileAttributes.class); | ||
BlobHttpHeaders headers = attr.blobHttpHeaders(); | ||
``` | ||
|
||
Or read attributes dynamically by specifying a string of desired attributes. This will not improve performance as a call | ||
to retrieve any attribute will always retrieve all of them as an atomic bulk operation. You may specify "*" instead of a | ||
list of specific attributes to have all attributes returned in the map. | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L84-L84 --> | ||
```java | ||
Map<String, Object> attributes = Files.readAttributes(filePath, "azureBlob:metadata,headers"); | ||
``` | ||
|
||
### Write attributes to a file | ||
|
||
Set attributes of a file through the `AzureBlobFileAttributeView`. | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L88-L89 --> | ||
```java | ||
AzureBlobFileAttributeView view = Files.getFileAttributeView(filePath, AzureBlobFileAttributeView.class); | ||
view.setMetadata(Collections.EMPTY_MAP); | ||
``` | ||
|
||
Or set an attribute dynamically by specifying the attribute as a string. | ||
|
||
<!-- embedme ./src/samples/java/com/azure/storage/blob/nio/ReadmeSamples.java#L93-L93 --> | ||
```java | ||
Files.setAttribute(filePath, "azureBlob:blobHttpHeaders", new BlobHttpHeaders()); | ||
``` | ||
|
||
## Troubleshooting | ||
|
||
When interacting with blobs using this Java client library, errors returned by the service correspond to the same HTTP | ||
status codes returned for [REST API][error_codes] requests. For example, if you try to retrieve a container or blob that | ||
doesn't exist in your Storage Account, a `404` error is returned, indicating `Not Found`. | ||
When using the NIO implementation for Azure Blob Storage, errors returned by the service are manifested as an | ||
`IOException` which wraps a `BlobStorageException` having the same HTTP status codes returned for | ||
[REST API][error_codes] requests. For example, if you try to read a file that doesn't exist in your Storage Account, a | ||
`404` error is returned, indicating `Not Found`. | ||
|
||
### Default HTTP Client | ||
All client libraries by default use the Netty HTTP client. Adding the above dependency will automatically configure | ||
|
@@ -137,12 +268,29 @@ operations. The Boring SSL library is an uber jar containing native libraries fo | |
better performance compared to the default SSL implementation within the JDK. For more information, including how to | ||
reduce the dependency size, refer to the [performance tuning][performance_tuning] section of the wiki. | ||
|
||
## Next steps | ||
|
||
Several Storage blob Java SDK samples are available to you in the SDK's GitHub repository. These samples provide example code for additional scenarios commonly encountered while working with Key Vault: | ||
|
||
## Next steps Samples | ||
Samples are explained in detail [here][samples_readme]. | ||
## Continued development | ||
|
||
This project is still actively being developed in an effort to move from preview to GA. Below is a list of features that | ||
are not currently supported but are under consideration and may be added before GA. We welcome feedback and input on | ||
which of these may be most useful and are open to suggestions for items not included in this list. While all of these | ||
items are being considered, they have not been investigated and designed and therefore we cannot confirm their | ||
feasibility within Azure Blob Storage. Therefore, it may be the case that further investigation reveals a feature may | ||
not be possible or otherwise may conflict with established design goals and therefor will not ultimately be supported. | ||
|
||
- Symbolic links | ||
- Hard links | ||
- Hidden files | ||
- Random writes | ||
- File locks | ||
- Watches on directory events | ||
- Support for other Azure Storage services such as ADLS Gen 2 (Datalake) and Azure Files (shares) | ||
- Token authentication | ||
- Multi-account filesystems | ||
- Delegating access to single files | ||
- Normalizing directory structure of data upon loading a FileSystem | ||
- Local caching | ||
- Other `OpenOptions` such as append or dsync | ||
- Flags to toggle certain behaviors such as FileStore (container) creation, etc. | ||
|
||
## Contributing | ||
|
||
|
@@ -159,18 +307,21 @@ This project has adopted the [Microsoft Open Source Code of Conduct][coc]. For m | |
[rest_docs]: https://docs.microsoft.com/rest/api/storageservices/blob-service-rest-api | ||
[product_docs]: https://docs.microsoft.com/azure/storage/blobs/storage-blobs-overview | ||
[sas_token]: https://docs.microsoft.com/azure/storage/common/storage-dotnet-shared-access-signature-part-1 | ||
[shared_key]: https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key | ||
[jdk]: https://docs.microsoft.com/java/azure/jdk/ | ||
[azure_subscription]: https://azure.microsoft.com/free/ | ||
[storage_account]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal | ||
[storage_account_create_cli]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-cli | ||
[storage_account_create_portal]: https://docs.microsoft.com/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal | ||
[identity]: https://github.com/Azure/azure-sdk-for-java/blob/master/sdk/identity/azure-identity/README.md | ||
[error_codes]: https://docs.microsoft.com/rest/api/storageservices/blob-service-error-codes | ||
[samples]: src/samples | ||
[samples]: https://docs.oracle.com/javase/tutorial/essential/io/fileio.html | ||
[cla]: https://cla.microsoft.com | ||
[coc]: https://opensource.microsoft.com/codeofconduct/ | ||
[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/ | ||
[coc_contact]: mailto:opencode@microsoft.com | ||
[performance_tuning]: https://github.com/Azure/azure-sdk-for-java/wiki/Performance-Tuning | ||
[file_system]: https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html | ||
[file_systems]: https://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystems.html | ||
|
||
 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
samples link goes to 404
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm debating whether I should add samples or if it's redundant because once you load the file system provider, it's the same thing as just using normal file apis. Thoughts? @alzimmermsft @kasobol-msft
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does NIO have some samples we could link to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think probably the oracle tutorials are sufficient. https://docs.oracle.com/javase/tutorial/essential/io/fileio.html