javaazureazure-files

How to get file content (byte array) from azure file storage using CloudFileClient?


I have file storage on azure and I am connecting and traversing threw the directories successfully. But I can't get the content of the file. For getting the FileClientReference I am using the following code:

public CloudFileClient getFileClientReference() {
    log.info("Logging into azure file storage:");
    CloudFileClient cloudFileClient = null;

    CloudStorageAccount storageAccount;
    try {
        storageAccount = CloudStorageAccount.parse(storageConnectionString);
        cloudFileClient = storageAccount.createCloudFileClient();
    } catch (IllegalArgumentException | URISyntaxException e) {
        log.error("Connection string specifies an invalid URI.");
        log.error("Please confirm the connection string is in the Azure connection string format.");
        throw new AzureFileStorageNotAvailableException("Failed to login to azure file storage.");
    } catch (InvalidKeyException e) {
        log.error("Connection string specifies an invalid key.");
        log.error("Please confirm the AccountName and AccountKey in the connection string are valid.");
        throw new AzureFileStorageNotAvailableException("Failed to login to azure file storage.");
    }
    log.info("Logged into azure file storage.");
    return cloudFileClient;
}

I have tested this code and it's working fine. I used it to traverse all the directories. What I am trying now to do is for a given url to get file content. The code that I am using to get the url is:

Iterable<ListFileItem> results = rootDir.listFilesAndDirectories();
    for (ListFileItem item : results) {
        boolean isDirectory = item.getClass() == CloudFileDirectory.class;
        final String uri = item.getUri().toString();
        if (isDirectory && uri.contains("myPath")) {
            traverseDirectories((CloudFileDirectory) item, azureFiles);
        } else if (!isDirectory) {
            handleFile(item, uri, azureFiles);
        }
    }

And in the end the result is something like:

https://appnamedev.file.core.windows.net/mystorage/2018/status/somepdf.pdf

Now I want to use this url to later get the file content as byte array and for that I am using the following code:

 fileClientReference.getShareReference(document.getPath())
                 .getRootDirectoryReference().getFileReference(document.getFileName()).openRead();

Where document.getPath() will point to the above mentioned path and document.getFileName() will give the file name: somepdf.pdf.

When I am calling this method I am getting an error:

Method threw 'com.microsoft.azure.storage.StorageException' exception.
The specifed resource name contains invalid characters.

The pdf is ok but I don't know how to access the pdf and get the content.


Solution

  • If anyone is also trying to figure out how to do this here is an answer: First when you are calling the method:

    fileClientReference.getShareReference(document.getPath())
    

    the path should be in the following format:

    /folder1/folder2/folder3/
    

    Without the prefix from azure:

    https://appnamedev.file.core.windows.net

    and without the file name as I was trying before. I have parsed that by calling replaceAll on the string.

    In one method I have:

    CloudFile cloudFile;
        try {
            String fileLocation = document.getPath().replaceAll(AZURE_FILE_STORAGE_URL_PREFIX + "|" + document.getFileName(), "");
            final CloudFileShare fileShare = fileClientReference.getShareReference(fileLocation);
            cloudFile = fileShare.getRootDirectoryReference().getFileReference(document.getFileName());
            return new AzureFile(document.getFileName(), readFileContent(cloudFile));
        } catch (URISyntaxException | StorageException e) {
            log.error("Failed to retrieve file for document with id: {}", documentId, e);
            throw new AzureFileStorageNotAvailableException("Failed to retrieve file");
        }
    

    And the readFileContent method is:

    private ByteArrayResource readFileContent(CloudFile cloudFile) {
        try (final FileInputStream fileInputStream = cloudFile.openRead()) {
            final byte[] content = fileInputStream.readAllBytes();
            return new ByteArrayResource(content);
        } catch (StorageException | IOException e) {
            log.error("Failed to read file content", e);
            throw new AzureFileStorageNotAvailableException("Failed to read file");
        }
    }
    

    The AzureFile is an entity that I have created on my own since I needed to pass the file name and the content:

    @Data
    @AllArgsConstructor
    public class AzureFile {
    
        private String fileName;
        private ByteArrayResource content;
    }