Пример #1
0
        /// <summary>
        /// Creates a new folder in this storage. If storage supports hierarchy, the folder is created as is, otherwise a folder is created by putting a dummy zero size file in that folder.
        /// </summary>
        /// <param name="blobStorage"></param>
        /// <param name="folderPath">Path to the folder</param>
        /// <param name="dummyFileName">If storage doesn't support hierary, you can override the dummy file name created in that empty folder.</param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public static async Task CreateFolderAsync(
            this IBlobStorage blobStorage, string folderPath, string dummyFileName = null, CancellationToken cancellationToken = default)
        {
            if (blobStorage is IHierarchicalBlobStorage hierarchicalBlobStorage)
            {
                await hierarchicalBlobStorage.CreateFolderAsync(folderPath, cancellationToken);
            }
            else
            {
                string fullPath = StoragePath.Combine(folderPath, dummyFileName ?? ".empty");

                await blobStorage.WriteTextAsync(
                    fullPath,
                    "created as a workaround by Storage.Net when creating an empty parent folder",
                    null,
                    cancellationToken);
            }
        }
Пример #2
0
        public static Blob ToBlob(string containerName, string path, BlobProperties properties)
        {
            string GetFullName(string name) => containerName == null
            ? name
            : StoragePath.Combine(containerName, name);

            var blob = new Blob(GetFullName(path), BlobItemKind.File);

            blob.MD5  = properties.ContentHash.ToHexString();
            blob.Size = properties.ContentLength;
            blob.LastModificationTime = properties.LastModified;

            AddProperties(blob, properties);

            blob.Metadata.MergeRange(properties.Metadata);

            return(blob);
        }
Пример #3
0
        internal static string GetBlobPath(DbFile file)
        {
            var    guidIinitialPart = file.Id.ToString().Split(new[] { '-' })[0];
            var    fileName         = file.FilePath.Split(new[] { '/' }).Last();
            var    depth1Folder     = guidIinitialPart.Substring(0, 2);
            var    depth2Folder     = guidIinitialPart.Substring(2, 2);
            string filenameExt      = Path.GetExtension(fileName);


            if (!string.IsNullOrWhiteSpace(filenameExt))
            {
                return(StoragePath.Combine(depth1Folder, depth2Folder, file.Id + filenameExt));
            }
            else
            {
                return(StoragePath.Combine(depth1Folder, depth2Folder, file.Id.ToString()));
            }
        }
Пример #4
0
        private async Task ListFolderAsync(List <BlobId> container, string path, ListOptions options, CancellationToken cancellationToken)
        {
            CloudBlobDirectory dir = GetCloudBlobDirectory(path);

            BlobContinuationToken token = null;

            var batch = new List <BlobId>();

            do
            {
                BlobResultSegment segment = await dir.ListBlobsSegmentedAsync(
                    false, BlobListingDetails.None, null, token, null, null, cancellationToken);

                token = segment.ContinuationToken;

                foreach (IListBlobItem blob in segment.Results)
                {
                    BlobId id = ToBlobId(blob, options.IncludeMetaWhenKnown);

                    if (options.IsMatch(id) && (options.BrowseFilter == null || options.BrowseFilter(id)))
                    {
                        batch.Add(id);
                    }
                }
            }while (token != null && ((options.MaxResults == null) || (container.Count + batch.Count < options.MaxResults.Value)));

            batch = batch.Where(options.IsMatch).ToList();
            if (options.Add(container, batch))
            {
                return;
            }

            if (options.Recurse)
            {
                List <BlobId> folderIds = batch.Where(r => r.Kind == BlobItemKind.Folder).ToList();

                await Task.WhenAll(
                    folderIds.Select(folderId => ListFolderAsync(
                                         container,
                                         StoragePath.Combine(path, folderId.Id),
                                         options,
                                         cancellationToken)));
            }
        }
Пример #5
0
        public async Task Sas_BlobPublicAccess()
        {
            string path = StoragePath.Combine("test", Guid.NewGuid().ToString() + ".txt");

            await _native.WriteTextAsync(path, "read me!");

            var policy = new BlobSasPolicy(DateTime.UtcNow, TimeSpan.FromHours(12))
            {
                Permissions = BlobSasPermission.Read | BlobSasPermission.Write
            };

            string publicUrl = await _native.GetBlobSasAsync(path);

            Assert.NotNull(publicUrl);

            string text = await new HttpClient().GetStringAsync(publicUrl);

            Assert.Equal("read me!", text);
        }
Пример #6
0
      public async Task List_FilesInFolder_Recursive()
      {
         string id1 = RandomGenerator.RandomString;
         string id2 = StoragePath.Combine(RandomGenerator.RandomString, RandomGenerator.RandomString);
         string id3 = StoragePath.Combine(RandomGenerator.RandomString, RandomGenerator.RandomString, RandomGenerator.RandomString);

         try
         {
            await _storage.WriteTextAsync(id1, RandomGenerator.RandomString);
            await _storage.WriteTextAsync(id2, RandomGenerator.RandomString);
            await _storage.WriteTextAsync(id3, RandomGenerator.RandomString);

            IEnumerable<BlobId> items = await _storage.ListAsync(new ListOptions { Recurse = true });
         }
         catch(NotSupportedException)
         {
            //it ok for providers not to support hierarchy
         }
      }
Пример #7
0
        public async Task Rename_File_Renames()
        {
            string prefix = RandomBlobPath();
            string file   = StoragePath.Combine(prefix, "1");

            try
            {
                await _storage.WriteTextAsync(file, "test");

                await _storage.RenameAsync(file, StoragePath.Combine(prefix, "2"));

                IReadOnlyCollection <Blob> list = await _storage.ListAsync(prefix);

                Assert.Single(list);
                Assert.True(list.First().Name == "2");
            }
            catch (NotSupportedException)
            {
            }
        }
Пример #8
0
        private BlobId ToBlobId(IListBlobItem blob, bool attachMetadata)
        {
            BlobId id;

            if (blob is CloudBlockBlob blockBlob)
            {
                string fullName = _prependContainerName
               ? StoragePath.Combine(_container.Name, blockBlob.Name)
               : blockBlob.Name;

                id = new BlobId(fullName, BlobItemKind.File);
            }
            else if (blob is CloudAppendBlob appendBlob)
            {
                string fullName = _prependContainerName
               ? StoragePath.Combine(_container.Name, appendBlob.Name)
               : appendBlob.Name;

                id = new BlobId(fullName, BlobItemKind.File);
            }
            else if (blob is CloudBlobDirectory dirBlob)
            {
                string fullName = _prependContainerName
               ? StoragePath.Combine(_container.Name, dirBlob.Prefix)
               : dirBlob.Prefix;

                id = new BlobId(fullName, BlobItemKind.Folder);
            }
            else
            {
                throw new InvalidOperationException($"unknown item type {blob.GetType()}");
            }

            //attach metadata if we can
            if (attachMetadata && blob is CloudBlob cloudBlob)
            {
                id.Meta = AzureUniversalBlobStorageProvider.GetblobMeta(cloudBlob);
            }

            return(id);
        }
        public void Combining()
        {
            StoragePath path = new StoragePath();

            path += "C:/";
            Assert.AreEqual(@"C:", path.ToString());

            path += (StoragePath)(new Uri("some/other", UriKind.RelativeOrAbsolute));
            Assert.AreEqual(@"C:\some\other", path.ToString());

            path = path.Combine("some///malformed\\\\other.some").SetExtension(".txt");
            Assert.AreEqual(@"C:\some\other\some\malformed\other.txt", path.ToString());

            path = path.SetExtension("txt");
            Assert.AreEqual(@"C:\some\other\some\malformed\other.txt", path.ToString());

            Assert.AreEqual("other.txt", path.ScopeToName().ToString());
            Assert.AreEqual("other", path.ScopeToNameWithoutExtension().ToString());
            Assert.AreEqual(@"C:\some\other\some\malformed", path.ParentDirectory.ToString());
            Assert.AreEqual(@"C:\some\other\some", path.GetNthParentDirectory(2).ToString());
        }
Пример #10
0
        public async Task Acl_get_with_upn()
        {
            string path   = StoragePath.Combine(Filesystem, Guid.NewGuid().ToString());
            string userId = _settings.AzureDataLakeGen2TestObjectId;

            //write something
            await _storage.WriteTextAsync(path, "perm?");

            //check that user has no permissions
            AccessControl access = await _storage.GetAccessControlAsync(path, true);

            Assert.DoesNotContain(access.Acl, x => x.Identity == userId);

            //assign user a write permission
            access.Acl.Add(new AclEntry(ObjectType.User, userId, false, true, false));
            await _storage.SetAccessControlAsync(path, access);

            //check user has permissions now
            access = await _storage.GetAccessControlAsync(path, true);

            Assert.True(access.Acl.First().Identity.Contains('@'));
        }
Пример #11
0
        private async Task <IReadOnlyCollection <Blob> > ListPathAsync(string path, int?maxResults, ListOptions options, CancellationToken cancellationToken)
        {
            //get filesystem name and folder path
            string[] parts = StoragePath.Split(path);

            string fs           = parts[0];
            string relativePath = StoragePath.Combine(parts.Skip(1));

            PathList list;

            try
            {
                list = await _api.ListPathAsync(fs, relativePath, recursive : options.Recurse).ConfigureAwait(false);
            }
            catch (ApiException ex) when(ex.StatusCode == HttpStatusCode.NotFound)
            {
                // specified path is not found, nothing serious
                return(new List <Blob>());
            }

            IEnumerable <Blob> result = list.Paths.Select(p => LConvert.ToBlob(fs, p));

            if (options.FilePrefix != null)
            {
                result = result.Where(b => b.IsFolder || b.Name.StartsWith(options.FilePrefix));
            }

            if (options.BrowseFilter != null)
            {
                result = result.Where(b => options.BrowseFilter(b));
            }

            if (maxResults != null)
            {
                result = result.Take(maxResults.Value);
            }

            return(result.ToList());
        }
Пример #12
0
            /// <summary>
            ///     Handle
            /// </summary>
            /// <param name="command"></param>
            /// <param name="cancellationToken"></param>
            /// <returns></returns>
            public async Task <CommandResponse> Handle(UploadMultipleAttachmentCommand command, CancellationToken cancellationToken)
            {
                CommandResponse response = new CommandResponse()
                {
                    UploadedAttachments = new List <AttachmentModel>()
                };

                foreach (var commandFile in command.Files)
                {
                    AttachmentModel attachment = new
                                                 AttachmentModel();

                    // prepare the upload
                    string originalName     = System.IO.Path.GetFileName(commandFile.FileName);
                    string extension        = System.IO.Path.GetExtension(commandFile.FileName).ToLower();
                    string storedAsFileName = $"{attachment.Id}{extension}";
                    string fileFullPath     = StoragePath.Combine("attachments",
                                                                  storedAsFileName);

                    // upload
                    string fullPath = await _storageService.UploadFile(commandFile, fileFullPath);

                    attachment.FilePath = fullPath;

                    // prepare response
                    attachment.FileName         = storedAsFileName;
                    attachment.FileType         = extension;
                    attachment.ContentType      = commandFile.ContentType;
                    attachment.OriginalFileName = originalName;
                    attachment.Name             = originalName;
                    attachment.Description      = $"Attachment {originalName}";

                    response.UploadedAttachments.Add(attachment);
                }

                return(response);
            }
Пример #13
0
        private Blob ToBlob(IListBlobItem nativeBlob)
        {
            Blob blob;

            if (nativeBlob is CloudBlockBlob blockBlob)
            {
                string fullName = StoragePath.Combine(_container.Name, blockBlob.Name);

                blob = new Blob(fullName, BlobItemKind.File);
            }
            else if (nativeBlob is CloudAppendBlob appendBlob)
            {
                string fullName = StoragePath.Combine(_container.Name, appendBlob.Name);

                blob = new Blob(fullName, BlobItemKind.File);
            }
            else if (nativeBlob is CloudBlobDirectory dirBlob)
            {
                string fullName = StoragePath.Combine(_container.Name, dirBlob.Prefix);

                blob = new Blob(fullName, BlobItemKind.Folder);
            }
            else
            {
                throw new InvalidOperationException($"unknown item type {nativeBlob.GetType()}");
            }

            //attach metadata if we can
            if (nativeBlob is CloudBlob cloudBlob)
            {
                //no need to fetch attributes, parent request includes the details
                //await cloudBlob.FetchAttributesAsync().ConfigureAwait(false);
                AzureUniversalBlobStorageProvider.AttachBlobMeta(blob, cloudBlob);
            }

            return(blob);
        }
Пример #14
0
        public async Task List_FilesInFolder_Recursive()
        {
            string folderPath = RandomBlobPath();
            string id1        = StoragePath.Combine(folderPath, "1.txt");
            string id2        = StoragePath.Combine(folderPath, "sub", "2.txt");
            string id3        = StoragePath.Combine(folderPath, "sub", "3.txt");

            try
            {
                await _storage.WriteTextAsync(id1, RandomGenerator.RandomString);

                await _storage.WriteTextAsync(id2, RandomGenerator.RandomString);

                await _storage.WriteTextAsync(id3, RandomGenerator.RandomString);

                IReadOnlyCollection <Blob> items = await _storage.ListAsync(recurse : true, folderPath : folderPath);

                Assert.Equal(4, items.Count); //1.txt + sub (folder) + 2.txt + 3.txt
            }
            catch (NotSupportedException)
            {
                //it ok for providers not to support hierarchy
            }
        }
Пример #15
0
        public async Task Rename_Folder_Renames()
        {
            string prefix  = RandomBlobPath();
            string file1   = StoragePath.Combine(prefix, "old", "1.txt");
            string file11  = StoragePath.Combine(prefix, "old", "1", "1.txt");
            string file111 = StoragePath.Combine(prefix, "old", "1", "1", "1.txt");

            try
            {
                await _storage.WriteTextAsync(file1, string.Empty);
            }
            catch (NotSupportedException)
            {
                return;
            }

            await _storage.WriteTextAsync(file11, string.Empty);

            await _storage.WriteTextAsync(file111, string.Empty);

            await _storage.RenameAsync(StoragePath.Combine(prefix, "old"), StoragePath.Combine(prefix, "new"));

            IReadOnlyCollection <Blob> list = await _storage.ListAsync(prefix);
        }
Пример #16
0
        /// <summary>
        /// Mounts a storage to virtual path
        /// </summary>
        /// <param name="path"></param>
        /// <param name="storage"></param>
        public void Mount(string path, IBlobStorage storage)
        {
            if (path is null)
            {
                throw new ArgumentNullException(nameof(path));
            }
            if (storage is null)
            {
                throw new ArgumentNullException(nameof(storage));
            }

            path = StoragePath.Normalize(path);

            _mountPoints.Add(new Blob(path)
            {
                Tag = storage
            });

            string absPath = null;

            string[] parts = StoragePath.Split(path);

            if (parts.Length == 0) //mount at root
            {
                MountPath(path, storage, true);
            }
            else
            {
                for (int i = 0; i < parts.Length; i++)
                {
                    absPath = StoragePath.Combine(absPath, parts[i]);

                    MountPath(absPath, storage, i == parts.Length - 1);
                }
            }
        }
Пример #17
0
        private async Task <(BlobContainerClient, string)> GetPartsAsync(string fullPath, bool createContainer = true)
        {
            GenericValidation.CheckBlobFullPath(fullPath);

            fullPath = StoragePath.Normalize(fullPath);
            if (fullPath == null)
            {
                throw new ArgumentNullException(nameof(fullPath));
            }

            string containerName, relativePath;

            if (_containerName == null)
            {
                string[] parts = StoragePath.Split(fullPath);

                if (parts.Length == 1)
                {
                    containerName = parts[0];
                    relativePath  = string.Empty;
                }
                else
                {
                    containerName = parts[0];
                    relativePath  = StoragePath.Combine(parts.Skip(1)).Substring(1);
                }
            }
            else
            {
                containerName = _containerName;
                relativePath  = fullPath;
            }

            if (!_containerNameToContainerClient.TryGetValue(containerName, out BlobContainerClient container))
            {
                container = _client.GetBlobContainerClient(containerName);
                if (_containerName == null)
                {
                    try
                    {
                        //check if container exists
                        await container.GetPropertiesAsync().ConfigureAwait(false);
                    }
                    catch (RequestFailedException ex) when(ex.ErrorCode == "ContainerNotFound")
                    {
                        if (createContainer)
                        {
                            await container.CreateIfNotExistsAsync().ConfigureAwait(false);
                        }
                        else
                        {
                            return(null, null);
                        }
                    }
                }

                _containerNameToContainerClient[containerName] = container;
            }

            return(container, relativePath);
        }
Пример #18
0
 public void Combine_theory(string expected, string[] parts)
 {
     Assert.Equal(expected, StoragePath.Combine(parts));
 }
Пример #19
0
        /// <summary>
        /// moves file from source to destination location
        /// </summary>
        /// <param name="sourceFilepath"></param>
        /// <param name="destinationFilepath"></param>
        /// <param name="overwrite"></param>
        /// <returns></returns>
        public DbFile Move(string sourceFilepath, string destinationFilepath, bool overwrite = false)
        {
            if (string.IsNullOrWhiteSpace(sourceFilepath))
            {
                throw new ArgumentException("sourceFilepath cannot be null or empty");
            }

            if (string.IsNullOrWhiteSpace(destinationFilepath))
            {
                throw new ArgumentException("destinationFilepath cannot be null or empty");
            }

            sourceFilepath      = sourceFilepath.ToLowerInvariant();
            destinationFilepath = destinationFilepath.ToLowerInvariant();

            if (!sourceFilepath.StartsWith(FOLDER_SEPARATOR))
            {
                sourceFilepath = FOLDER_SEPARATOR + sourceFilepath;
            }

            if (!destinationFilepath.StartsWith(FOLDER_SEPARATOR))
            {
                destinationFilepath = FOLDER_SEPARATOR + destinationFilepath;
            }

            var srcFile  = Find(sourceFilepath);
            var destFile = Find(destinationFilepath);

            if (srcFile == null)
            {
                throw new Exception("Source file cannot be found.");
            }

            if (destFile != null && overwrite == false)
            {
                throw new Exception("Destination file already exists and no overwrite specified.");
            }

            using (var connection = CurrentContext.CreateConnection())
            {
                try
                {
                    connection.BeginTransaction();

                    if (destFile != null && overwrite)
                    {
                        Delete(destFile.FilePath);
                    }

                    var command = connection.CreateCommand(@"UPDATE files SET filepath = @filepath WHERE id = @id");
                    command.Parameters.Add(new NpgsqlParameter("@id", srcFile.Id));
                    command.Parameters.Add(new NpgsqlParameter("@filepath", destinationFilepath));
                    command.ExecuteNonQuery();
                    if (ErpSettings.EnableCloudBlobStorage)
                    {
                        var srcPath         = StoragePath.Combine(StoragePath.RootFolderPath, sourceFilepath);
                        var destinationPath = StoragePath.Combine(StoragePath.RootFolderPath, destinationFilepath);
                        using (IBlobStorage storage = GetBlobStorage())
                        {
                            using (Stream original = storage.OpenReadAsync(srcPath).Result)
                            {
                                if (original != null)
                                {
                                    storage.WriteAsync(destinationPath, original).Wait();
                                    storage.DeleteAsync(sourceFilepath).Wait();
                                }
                            }
                        }
                    }
                    else if (ErpSettings.EnableFileSystemStorage)
                    {
                        var srcFileName  = Path.GetFileName(sourceFilepath);
                        var destFileName = Path.GetFileName(destinationFilepath);
                        if (srcFileName != destFileName)
                        {
                            var fsSrcFilePath = GetFileSystemPath(srcFile);
                            srcFile.FilePath = destinationFilepath;
                            var fsDestFilePath = GetFileSystemPath(srcFile);
                            File.Move(fsSrcFilePath, fsDestFilePath);
                        }
                    }

                    connection.CommitTransaction();
                    return(Find(destinationFilepath));
                }
                catch
                {
                    connection.RollbackTransaction();
                    throw;
                }
            }
        }
 private string GenerateBlobPath(QueueMessage message)
 {
     return(StoragePath.Combine("message", Guid.NewGuid().ToString()));
 }
Пример #21
0
 private static string GetBlobName(string partitionId)
 {
     return(StoragePath.Combine("partition", $"{partitionId}.json"));
 }
Пример #22
0
 private string GetFullName(string name)
 {
     return(_prependContainerName
     ? StoragePath.Combine(_container.Name, name)
     : name);
 }
Пример #23
0
        public async Task ListFolder(List <BlobId> container, string path, ListOptions options, CancellationToken cancellationToken)
        {
            CloudBlobDirectory dir = GetCloudBlobDirectory(path);

            BlobContinuationToken token = null;

            var batch = new List <BlobId>();

            do
            {
                BlobResultSegment segment = await dir.ListBlobsSegmentedAsync(
                    false, BlobListingDetails.None, null, token, null, null, cancellationToken);

                token = segment.ContinuationToken;

                foreach (IListBlobItem blob in segment.Results)
                {
                    BlobId id;

                    if (blob is CloudBlockBlob blockBlob)
                    {
                        id = new BlobId(blockBlob.Name, BlobItemKind.File);
                    }
                    else if (blob is CloudAppendBlob appendBlob)
                    {
                        id = new BlobId(appendBlob.Name, BlobItemKind.File);
                    }
                    else if (blob is CloudBlobDirectory dirBlob)
                    {
                        id = new BlobId(dirBlob.Prefix, BlobItemKind.Folder);
                    }
                    else
                    {
                        throw new InvalidOperationException($"unknown item type {blob.GetType()}");
                    }

                    if (options.IsMatch(id))
                    {
                        batch.Add(id);
                    }
                }
            }while (token != null && ((options.MaxResults == null) || (container.Count + batch.Count < options.MaxResults.Value)));

            batch = batch.Where(options.IsMatch).ToList();
            if (options.Add(container, batch))
            {
                return;
            }

            if (options.Recurse)
            {
                List <BlobId> folderIds = batch.Where(r => r.Kind == BlobItemKind.Folder).ToList();
                foreach (BlobId folderId in folderIds)
                {
                    await ListFolder(
                        container,
                        StoragePath.Combine(path, folderId.Id),
                        options,
                        cancellationToken);
                }
            }
        }
Пример #24
0
        public async Task <IReadOnlyCollection <BlobId> > ListAsync(ListOptions options, CancellationToken cancellationToken = default)
        {
            if (options == null)
            {
                options = new ListOptions();
            }

            var result     = new List <BlobId>();
            var containers = new List <CloudBlobContainer>();

            if (_fixedContainer != null)
            {
                containers.Add(_fixedContainer);
            }
            else if (options.FolderPath == null)
            {
                // list all of the containers
                containers.AddRange(await GetCloudBlobContainersAsync(cancellationToken));

                //represent containers as folders in the result
                result.AddRange(containers.Select(c => new BlobId(c.Name, BlobItemKind.Folder)));
            }
            else
            {
                (CloudBlobContainer container, string path) = await GetPartsAsync(options.FolderPath, false);

                if (container == null)
                {
                    return(new List <BlobId>());
                }
                options.FolderPath = path; //scan from subpath now
                containers.Add(container);

                //add container as search result
                result.Add(new BlobId(container.Name, BlobItemKind.Folder));
            }

            foreach (CloudBlobContainer container in containers)
            {
                var browser = new AzureBlobDirectoryBrowser(container);
                IReadOnlyCollection <BlobId> containerBlobs = await browser.ListFolderAsync(options, cancellationToken);

                if (containerBlobs.Count > 0)
                {
                    if (_fixedContainer == null)
                    {
                        result.AddRange(containerBlobs.Select(bid => new BlobId(StoragePath.Combine(container.Name, bid.FullPath), bid.Kind)));
                    }
                    else
                    {
                        result.AddRange(containerBlobs);
                    }
                }

                if (options.MaxResults != null && result.Count >= options.MaxResults.Value)
                {
                    break;
                }
            }

            return(result);
        }