Only this pageAll pages
Powered by GitBook
1 of 24

v1.x

Loading...

Intro

Loading...

Loading...

Getting Started

Loading...

Loading...

Loading...

Loading...

Loading...

Usage

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Digging Deeper

Loading...

Loading...

Loading...

Release History

A brief history in time of our major releases

Here is a breakdown of our major version releases. In this section, you will find the release notes for each version we release. If you are looking for the release notes of previous major versions, use the version switcher at the top left of this documentation book.

Version 1

Our initial release! Woot Woot 🎉

Introduction

cbfs is a module for ColdBox that provides abstractions to any file system.

ColdBox File System Abstraction = cbfs

The cbfs module will enable you to abstract ANY filesystem within your ColdBox applications with a human, fluent, and consistent API. You can configure as many disks as you wish to represent file systems in your application. Each disk is backed by a storage provider and configurable within your ColdBox application. Each ColdBox Module can also provide and consume disks in an HMVC fashion.

Never worry about hard-coded paths or how to interact with different file systems or tiers, as your API will remain the same for each system.

Storage Providers

The available storage providers are

  • Local - A local file system storage provider.

  • Ram - An in-memory file storage provider.

  • S3 - An Amazon S3, Rackspace, Digital Ocean, or Google Cloud Storage provider.

System Requirements

  • Lucee 5+

  • Adobe ColdFusion 2018+

  • Java 11+

Versioning

cbfs is maintained under the Semantic Versioning guidelines as much as possible. We number releases in the following format:

<major>.<minor>.<patch>

And constructed with the following guidelines:

  • Breaking backward compatibility bumps the major (and resets the minor and patch)

  • New additions without breaking backward compatibility bump the minor (and reset the patch)

  • Bug fixes and miscellaneous changes bump the patch

License

The ColdBox Platform, cbfs is open source and licensed under the Apache 2 License.

  • Copyright by Ortus Solutions, Corp

  • ColdBox, CacheBox, WireBox, and LogBox are registered trademarks of Ortus Solutions, Corp.

Important Links

  • Code: https://github.com/coldbox-modules/cbfs

  • Issues: https://github.com/coldbox-modules/cbfs/issues

Professional Open Source

Ortus Solutions, Corp

The ColdBox Security Module is a professional open-source software backed by Ortus Solutions, Corp offering services like:

  • Custom Development

  • Professional Support & Mentoring

  • Training

  • Server Tuning

  • Security Hardening

  • Code Reviews

  • Much More

Discussion & Help

The Box products and modules community for discussion and help can be found here:

https://community.ortussolutions.com/c/box-modules/

HONOR GOES TO GOD ABOVE ALL

Because of His grace, this project exists. If you don't like this, don't read it; it's not for you.

"Therefore being justified by faith, we have peace with God through our Lord Jesus Christ: By whom also we have access by faith into this grace wherein we stand, and rejoice in hope of the glory of God." Romans 5:5

RAM Provider

The RAM provider leverages memory allocation for its file-system

Use the RAM provider to store files within available RAM.

The trade-off with the RAM provider is that IO operations will be performed incredibly fast, but you are limited to the available RAM that's been allocated to run your CFML application.

Configuration

Example

config/ColdBox.cfc
moduleSettings = {
	"cbfs": {
		// The default disk with a reserved name of 'default'
		"defaultDisk" : "myStorage",
		// Register the disks on the system
		"disks"       : {
			// Your default application storage
			"myStorage" : {
				"provider"   : "RAM",
				"properties" : {}
			}
		}
	},
};

Properties

When configuring your RAM disks, the following properties are available:

Property
Type
Default
Description

uploadMimeAccept

string

*

The mime types which are accepted via the upload method. Defaults to all.

About This Book

A little more info about this book

The source code for this book is hosted on GitHub: . You can freely contribute to it and submit pull requests. The contents of this book are copyrighted by and cannot be altered or reproduced without the author's consent. All content is provided "As-Is" and can be freely distributed.

  • The majority of code examples in this book are done in cfscript.

  • The majority of code generation and running of examples are done via CommandBox: The ColdFusion (CFML) CLI, Package Manager, REPL - ​

External Trademarks & Copyrights

Flash, Flex, ColdFusion, and Adobe are registered trademarks and copyrights of Adobe Systems, Inc.

Notice of Liability

The information in this book is distributed “as is” without warranty. The author and Ortus Solutions, Corp shall not have any liability to any person or entity concerning loss or damage caused or alleged to be caused directly or indirectly by the content of this training book, software, and resources described in it.

Contributing

We highly encourage contributions to this book and our open-source software. The source code for this book can be found in our GitHub repository, where you can submit pull requests.

Charitable Proceeds

Shalom Children’s Home is one of the ministries that are dear to our hearts in El Salvador. During the 12-year civil war that ended in 1990, many children were left orphaned or abandoned by parents who fled El Salvador. The Benners saw the need to help these children and received 13 children in 1982. Little by little, more children came on their own, churches and the government brought children to them for care, and the Shalom Children’s Home was founded. Shalom now cares for over 80 children in El Salvador, from newborns to 18 years old. They receive shelter, clothing, food, medical care, education, and life skills training in a Christian environment. A child sponsorship program supports the home. We have supported Shalom since 2009; it is a place of blessing for many El Salvador children who either have no families or have been abandoned. This is a good earth to seed and plant.

Providers

Here are the providers cbfs supports natively

https://github.com/ortus-docs/cbfs-docs
Ortus Solutions, Corp
https://www.ortussolutions.com/products/commandbox
The Provider Strategy Pattern
Local Provider
RAM Provider
S3 Provider

Module Disks

Use HMVC and define module disks

cbfs with HVMC

If you are creating your own ColdBox modules, you can create disks from those modules in the configure() lifecycle method in the ModuleConfig.cfc. You will do so by creating a cbfs key and adding either module disks or global disks.

  • disks : The collection of disks the module collaborates. Each name will be suffixed with the module name: key@moduleName

  • globalDisks : A collection of global name spaced disks the module contributes to the entire application.

component {
  function configure(){
	settings = {
	  // CBFS Module
	  cbfs : {
		// Disks that will be namespaced with the module name @diskModule
		// temp@diskModule
		// nasa@diskModule
		disks : {
			"temp" : { provider : "Ram" },
			"nasa" : { provider : "Ram" }
		},
		// No namespace in global spacing
		// temp
		// nasa
		globalDisks : {
			// Should be ignored, you can't override if it exists
			"temp" : { provider : "Ram" },
			"nasa" : { provider : "Ram" }
		}
	   }
	};
  }	
}

Configuration Methods

The configuration methods are most commonly used by cbfs internally to startup and shutdown disks. You should only have to call these methods directly for advanced use cases.

hasStarted

Returns true if the disk has been started up, false if not.

getIdentifier

Returns the unique UUID identifier for this disk.

getName

Returns the name of the disk.

getProperties

Returns the settings for the disk.

shutdown

cbfs invokes this method before the cbfs module is unloaded or during application reinit. You can implement this method as you see fit to shut down connections, sockets, etc.

startup

Start up a disk provider with the instance data it needs to start up. It must ensure that it sets the "started" variable to true to operate.

if ( !disk.hasStarted() ) {
    // Email Luis
}
var identifier = disk.getIdentifier(); // returns GUID
var name = disk.getName(); // returns name defined in ColdBox.cfc
var properties = disk.getProperties(); // returns struct

var isCDrive = properties.path == "C:\" ? true : false;
if ( disk.hasStarted() ) {
    disk.shutdown(); // No disk for you.
}
disk.startup( name="myDisk", properties={
    "path": "C:\somepath"
} );

Local Provider

The local provider leverages the Java Non Block io package.

Use the local provider to store files in a local filesystem where your application is running. Behind the scenes it leverages the Java nio package to provide concurrency, atomicity, and non-blocking operations.

Configuration

Example

config/ColdBox.cfc
moduleSettings = {
  "cbfs": {
	// The default disk with a reserved name of 'default'
	"defaultDisk" : "myStorage",
	// Register the disks on the system
	"disks"       : {
	  // Your default application storage
	  "myStorage" : {
		"provider"   : "Local",
		"properties" : { 
			"path" : "#controller.getAppRootPath()#.myStorage",
			"diskUrl" : function(){
				return variables.controller
					.getRequestService()
					.getContext()
					.getHtmlBaseUrl()
					& "storage/.mystorage/";
			}
		}
	  }
	}
  }
};

Properties

When configuring your local disks, the following properties are available:

Property
Type
Default
Description

autoExpand

Boolean

false

If true, it will use an expandPath() on the path property. Else it leaves it as is.

diskUrl

http(s)

null

The public disk Url. This is used to create file URLs and temporary URLs. This should point to the root path but in a web-accessible format.

path

string

--

The relative or absolute path of where to store the file system.

uploadMimeAccept

string

*

The mime types which are accepted via the upload method. Defaults to all.

visibility

string

public

The default visibility when creating files. Available options are public, private, readonly

Verification Methods

isExecutable

Returns true if the file is executable.

isFile

Verifies if the passed path is an existent file.

isHidden

Returns true if the file is hidden.

isReadable

Returns true if the file is readable.

isSymbolicLink

Returns true if the file is a symbolic link.

isWritable

Returns true if the file is writable.

Interceptors

There are that are announced when working with CBFS disks, directories, and files that you can use. These can be used to provide additional functionality in your applications such as logging file access, securing folders, and more.

cbfsOnDiskStart

Invoked after a disk has been started.

CBFS automatically manages the starting of disks.

cbfsOnDiskShutdown

CBFS automatically manages the shutdown of disks.

Invoked after a disk has been shutdown.

cbfsOnFileCreate

Invoked when a file is created.

cbfsOnFileMove

Invoked when a file is moved.

cbfsOnFileCopy

Invoked when a file is copied.

cbfsOnFileDelete

Invoked when a file is deleted.

cbfsOnFileInfoRequest

Invoked when info or extended info is requested on a file.

cbfsOnFileMove

Invoked when a file is moved.

cbfsOnDirectoryMove

Invoked when a directory is moved.

cbfsOnDirectoryCreate

Invoked when a directory is created.

cbfsOnDirectoryCopy

Invoked when a directory is copied.

cbfsOnDirectoryDelete

Invoked when a directory is deleted.

/**
 * @path The file path
 *
 * @throws cbfs.FileNotFoundException - If the filepath is missing
 */
boolean function isExecutable( required path );

// Example
if ( disk.isExecutable( "myFile.txt" ) ) {
    // Execute the file
}
/**
 * @path The file path
 *
 * @throws cbfs.FileNotFoundException
 */
boolean function isFile( required path );

// Example
if ( disk.isFile( "myFile.txt" ) ) {
    // Read the file
}
/**
 * @path The file path
 *
 * @throws cbfs.FileNotFoundException - If the filepath is missing
 */
boolean function isHidden( required path );

// Example
if ( !disk.isHidden( "myFile.txt" ) ) {
    // Read the file
}
/**
 * @path The file path
 *
 * @throws cbfs.FileNotFoundException - If the filepath is missing
 */
boolean function isReadable( required path );

// Example
if ( disk.isReadable( "myFile.txt" ) ) {
    // Read the file
}
/**
 * Is the file is a symbolic link
 *
 * @path The file path
 *
 * @throws cbfs.FileNotFoundException - If the filepath is missing
 */
boolean function isSymbolicLink( required path );

// Example
if ( !disk.isSymbolicLink( "myFile.txt" ) ) {
    // Read the file
}
/**
 * @path The file path
 *
 * @throws cbfs.FileNotFoundException - If the filepath is missing
 */
boolean function isReadable( required path );

// Example
if ( disk.isWritable( "myFile.txt" ) ) {
    // Write to the file
}
component {
      function cbfsOnDiskStart( disk ) {
            //java...
      }
}
component {
      function cbfsOnDiskShutdown( disk ) {
            //java...
      }
}
component {
    function cbfsOnFileCreate( file ) {
 
    }
}
component {
    function cbfsOnFileMove( file ) {
 
    }
}
component {
    function cbfsOnFileCopy( file ) {
 
    }
}
component {
    function cbfsOnFileDelete( file ) {
        
    }
}
component {
    function cbfsOnFileInfoRequest( file ) {
    
    }
}
component {
    function cbfsOnFileMove( file ) {
        
    }
}
component {
    function cbfsOnDirectoryMove( source, destination, disk ) {
    
    }
}
component {
    function cbfsOnDirectoryCreate( directory, disk ) {
    
    }
}
component {
    function cbfsOnDirectoryCopy( source, destination, disk ) {
    
    }
}
component {
    function cbfsOnDirectoryDelete( directory, disk ) {
    
    }
}
ColdBox interception points

Disk Service

cbfs includes a Disk Service object you can use to register and interact with your disks.

dThe full API for the Disk Service can be found in the API Docs.

Injection DSL

The cbfs module registers a WireBox injection DSL that you can use to inject objects from the module.

DSL
Description

cbfs

Inject the Disk Service

cbfs:disks

Inject the entire disk records

cbfs:disks:{name}

Inject a specific disk instance by {name}

// Injects the DiskService
diskService = getInstance( "cbfs" );
property name="diskService" inject="cbfs";

diskService = getInstance( "DiskService@cbfs" );
property name="diskService" inject="DiskService@cbfs";

// Injects the entire disks record structure
disks = getInstance( "cbfs:disks" );
property name="disks" inject="cbfs:disks";

// Injects a specific disk by name
tempDisk = getInstance( "cbfs:disks:{name}" );
tempDisk = getInstance( "cbfs:disks:temp" );
property name="tempDisk" inject="cbfs:disks:temp";

Helper Method

The cbfs module registers a helper method called cbfs( diskName ) that you can use in your handlers, layouts, and views to get an instance of a specific disk:

// SomeHandler.cfc
component {
    function index( event, rc, prc ) {
        var storage = cbfs( "RamDisk" );
        var files = storage.allFiles();
    }
}

Core Methods

count()

Returns the count of registered disks.

defaultDisk()

Return an instance of the default disk defined in your configuration.

get( name )

Returns requested disk instance. Throws InvalidDiskException if the disk is not registered.

getDiskRecord( name )

Returns struct of details for a disk.

has( name )

Returns true if the disk has been registered with the provided name.

names()

Returns an array of registered disk names.

register( name, provider, properties, override )

Registers a new disk. If a disk has already been configured with the same name, then it will not be updated unless you specify override=true.

shutdown()

Unregisters and shuts down all disks managed by the DiskService.

tempDisk()

Returns the temporary disk.

unregister( name )

Unregisters a disk. Throws InvalidDiskException if the disk is not registered.

Installation

Get up and running with cbfs in no time!

Use to install:

To install the bleeding-edge version:

Configuration

You can configure the module by adding a cbfs structure to the moduleSettings in your config/Coldbox.cfc file or you can create your own config/modules/cbfs.cfc configuration file if you are using ColdBox 7. Below you can see the default configuration for cbfs.

Pre-Configured Disks

By default, cbfs, comes pre-configured with 3 disks:

Disk Name
Provider
Location
Description

Environment Variables

Please note that you can change the location of these disks by adding the configuration or you can easily do so using the following environment variables:

  • CBFS_DEFAULT_DISK_PATH

  • CBFS_PUBLIC_DISK_PATH

  • CBFS_TEMP_DISK_PATH

Default Disk

You can use the defaultDisk key to specify which disk will be the default in your system. By default it's the default one 😂 which is not web-accessible and stored as .cbfs in your root application.

Registering Disks

The disks structure is used to register disks in your application. The key is the name of the disk which is a structure that each disk needs in order to be configured:

  • provider : The name of the provider (if core) or a full CFC path or WireBox ID

  • properties : A structure of configuration properties the disk requires (if any)

Please check out the section in order to see the properties and requirements for each one of them.

install cbfs
install cbfs@be
config/modules/cbfs.cfc
function configure(){
    return {
    	// The default disk with a reserved name of 'default'
	"defaultDisk" : "default",
	// Register the disks on the system
	"disks"       : {
		// Your default application storage : non-web accessible
		"default" : {
			provider   : "Local",
			properties : {
				path : getSystemSetting( "CBFS_DEFAULT_DISK_PATH", "#controller.getAppRootPath()#.cbfs" )
			}
		},
		// A public web-accessible storage located at /includes/public
		"public" : {
			provider   : "Local",
			properties : {
				path : getSystemSetting(
					"CBFS_PUBLIC_DISK_PATH",
					"#controller.getAppRootPath()#includes/public"
				),
				diskUrl : function(){
					return variables.controller
						.getRequestService()
						.getContext()
						.getHtmlBaseUrl() & "includes/public"
				}
			}
		},
		// A disk that points to the CFML Engine's temp directory
		"temp" : {
			provider   : "Local",
			properties : { path : getSystemSetting( "CBFS_TEMP_DISK_PATH", getTempDirectory() ) }
		}
	}
   };
}

default

Local

{app}/.cbfs

A private location for assets

public

Local

{app}/includes/public

A public accessible location inside of your application

temp

Local

{CF internal}

The Java temp internal directory

CommandBox CLI
providers

File Methods

append

Append contents to the end of a file.

/**
 * @path           The file path to use for storage
 * @contents       The contents of the file to append
 * @metadata       Struct of metadata to store with the file
 * @throwOnMissing Boolean flag to throw if the file is missing. Otherwise it will be created if missing.
 *
 * @return LocalProvider
 *
 * @throws cbfs.FileNotFoundException
 */
function append(
	required string path,
	required contents,
	struct metadata        = {},
	boolean throwOnMissing = false
);

copy

Copy a file from one destination to another.

/**
 * @source      The source file path
 * @destination The end destination path
 * @overwrite   Flag to overwrite the file at the destination, if it exists. Defaults to true.
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.FileNotFoundException - When the source doesn't exist
 * @throws cbfs.FileOverrideException - When the destination exists and no override has been provided
 */
function copy(
	required source,
	required destination,
	boolean overwrite = true
);

create

Create a file on the disk.

/**
 * @path       The file path to use for storage
 * @contents   The contents of the file to store
 * @visibility The storage visibility of the file, available options are `public, private, readonly` or a custom data type the implemented driver can interpret
 * @metadata   Struct of metadata to store with the file
 * @overwrite  Flag to overwrite the file at the destination, if it exists. Defaults to true.
 * @mode       Applies to *nix systems. If passed, it overrides the visbility argument and uses these octal values instead
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.FileOverrideException - When a file exists and no override has been provided
 */
function create(
	required path,
	required contents,
	string visibility = "public",
	struct metadata   = {},
	boolean overwrite = true,
	string mode
);

createFromFile

Creates a disk object directly from a file, rather than reading the file contents in to memory

/**
* Create a file in the disk from a file path
*
* @source       The file path to use for storage
* @directory    The target directory
* @name         The destination file name. If not provided it defaults to the file name from the source
* @visibility   The storage visibility of the file, available options are `public, private, readonly` or a custom data type the implemented driver can interpret
* @overwrite    Flag to overwrite the file at the destination, if it exists. Defaults to true.
* @deleteSource Flag to remove the source file upon creation in the disk.  Defaults to false.
*
* @return cbfs.models.IDisk
*
* @throws cbfs.FileOverrideException - When a file exists and no override has been provided
*/
function createFromFile(
	required source,
	required directory,
	string name,
	string visibility    = variables.properties.visibility,
	boolean overwrite    = true,
	boolean deleteSource = false
);

upload

Uploads a file directly in to disk storage

/**
 * Uploads a file in to the disk
 *
 * @fieldName The file field name
 * @directory the directory on disk to upload to
 * @fileName  optional file name on the disk
 * @overwrite whether to overwrite ( defaults to false )
 */
function upload(
	required fieldName,
	required directory,
	string fileName,
	string overwrite = false
);

download

Delivers a file directly to the browser

/**
* Download a file to the browser
*
* @path The file path to download
*
* @throws cbfs.FileNotFoundException
*/
string function download( required path )

delete

Delete a file or an array of file paths. If a file does not exist, false will be returned.

/**
 * @path           A single file path or an array of file paths
 * @throwOnMissing Boolean to throw an exception if the file is missing.
 *
 * @return boolean or struct report of deletion
 *
 * @throws cbfs.FileNotFoundException
 */
boolean function delete( required any path, boolean throwOnMissing = false );

exists

Validate if a file exists.

/**
 * @path The file path to verify
 */
boolean function exists( required string path );

file

Returns a File Object that you can use for simpler API access.

/**
 * Returns a File object for simplier API access
 *
 * @path The file path to check
 * @contents The contents of the file to set
 */
File function file( required path, contents );

missing

Validate if a file doesn't exist.

/**
 * @path The file path to verify
 */
boolean function missing( required string path );

get

Get the contents of a file.

/**
 * @path The file path to retrieve
 *
 * @return The contents of the file
 *
 * @throws cbfs.FileNotFoundException
 */
any function get( required path );

getAsBinary

Get the contents of a file as binary, such as an executable or image.

/**
 * @path The file path to retrieve
 *
 * @return A binary representation of the file
 *
 * @throws cbfs.FileNotFoundException
 */
any function getAsBinary( required path );

move

Move a file from one destination to another.

/**
 * @source      The source file path
 * @destination The end destination path
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.FileNotFoundException - When the source doesn't exist
 * @throws cbfs.FileOverrideException - When the destination exists and no override has been provided
 */
function move(
	required source,
	required destination,
	boolean overwrite = true
);

prepend

Prepend contents to the beginning of a file. This method can be a costly operation for local disk storage.

/**
 * @path           The file path to use for storage
 * @contents       The contents of the file to prepend
 * @metadata       Struct of metadata to store with the file
 * @throwOnMissing Boolean flag to throw if the file is missing. Otherwise it will be created if missing.
 *
 * @return LocalProvider
 *
 * @throws cbfs.FileNotFoundException
 */
function prepend(
	required string path,
	required contents,
	struct metadata        = {},
	boolean throwOnMissing = false
);

touch

Create a new empty file if it does not exist.

/**
 * @path       The file path
 * @createPath if set to false, expects all parent directories to exist, true will generate necessary directories. Defaults to true.
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.PathNotFoundException
 */
function touch( required path, boolean createPath = true );

File Object

The CBFS File object gives you simplied access to the disk API.

To create a new file object, you an use:

var file = disk.file( "some/path/somefile.txt" );

Then you can access any of the api methods documented here. Enjoy!

var file = disk.file( "somefile.txt" )
                .create( "some contents" )
                .append( "append contents" );
                
var mimeType = file.mimeType(); // returns 'text/plain'

append

Append contents to the end of a file.

/**
 * @contents       The contents of the file to append
 * @metadata       Struct of metadata to store with the file
 * @throwOnMissing Boolean flag to throw if the file is missing. Otherwise it will be created if missing.
 *
 * @return File
 *
 * @throws cbfs.FileNotFoundException
 */
function append(
	required contents,
	struct metadata        = {},
	boolean throwOnMissing = false
);

checksum

Generate checksum for a file in different hashing algorithms.

/**
 * Generate checksum for a file in different hashing algorithms
 *
 * @algorithm Default is MD5, but SHA-1, SHA-256, and SHA-512 can also be used.
 *
 * @throws cbfs.FileNotFoundException
 */
string function checksum( algorithm = "MD5" );

chmod

Sets the access attributes of the file on Unix based disks.

/**
 * @mode Access mode, the same attributes you use for the Linux command `chmod`
 * @return File
 */
function chmod( required string mode );

copy

Copy a file from one destination to another.

/**
* @destination The end destination path
* @overwrite   Flag to overwrite the file at the destination, if it exists. Defaults to true.
*
* @return File  - returns the copied file object
*
* @throws cbfs.FileNotFoundException - When the source doesn't exist
* @throws cbfs.FileOverrideException - When the destination exists and no override has been provided
*/
function copy(
   required destination,
   boolean overwrite = true
);

create

Creates a file on the disk.

/**
 * @contents   The contents of the file to store
 * @visibility The storage visibility of the file, available options are `public, private, readonly` or a custom data type the implemented driver can interpret
 * @metadata   Struct of metadata to store with the file
 * @overwrite  Flag to overwrite the file at the destination, if it exists. Defaults to true.
 * @mode       Applies to *nix systems. If passed, it overrides the visbility argument and uses these octal values instead
 *
 * @return File
 *
 * @throws cbfs.FileOverrideException - When a file exists and no override has been provided
 */
function create(
	required contents,
	string visibility,
	struct metadata   = {},
	boolean overwrite = true,
	string mode
);

delete

Delete a file or an array of file paths. If a file does not exist a false will be shown for its return.

/**
 * @throwOnMissing Boolean to throw an exception if the file is missing.
 *
 * @return boolean
 *
 * @throws cbfs.FileNotFoundException
 */
boolean function delete( boolean throwOnMissing = false );

exists

Validate if a file exists.

/**
* @path The file path to verify
*/
boolean function exists();

extension

Extract the extension from the file path.

string function extension();

get

Get the contents of a file.

/**
* @return The contents of the file
*
* @throws cbfs.FileNotFoundException
*/
any function get();

info

Return information about the file. Will contain keys such as lastModified, size, path, name, type, canWrite, canRead, isHidden and more depending on the provider used.

/**
* @return A struct of file metadata according to provider
*
* @throws cbfs.FileNotFoundException
*/
struct function info();

isExecutable

Returns true if the file is executable.

/**
* @throws cbfs.FileNotFoundException - If the filepath is missing
* 
* @return Boolean
*/
boolean function isExecutable();

isHidden

Returns true if the file is hidden.

/**
* @throws cbfs.FileNotFoundException - If the filepath is missing
* 
* @return Boolean
*/
boolean function isHidden();

isReadable

Returns true if the file is readable.

/**
* @return Boolean
*/
boolean function isReadable();

isSymbolicLink

Returns true if the file is a symbolic link.

/**
 * @throws cbfs.FileNotFoundException - If the filepath is missing
 * @return Boolean
 */
boolean function isSymbolicLink();

isWritable

Returns true if the file is writable.

/**
* @return Boolean
*/
boolean function isWritable();

lastModified

Retrieve the file's last modified timestamp.

/**
* @throws cbfs.FileNotFoundException
*/
function lastModified();

mimeType

Retrieve the file's mime type.

/**
 * Retrieve the file's mimetype
 * @return String
 * @throws cbfs.FileNotFoundException
 */
function mimeType();

move

Move a file from one destination to another.

/**
 * @destination The end destination path
 *
 * @return File - the moved file object
 *
 * @throws cbfs.FileNotFoundException - When the source doesn't exist
 * @throws cbfs.FileOverrideException - When the destination exists and no override has been provided
 */
function move(
	required destination,
	boolean overwrite = true
);

prepend

Prepend contents to the beginning of a file. This is a very expensive operation for local disk storage.

/**
* @contents       The contents of the file to prepend
* @metadata       Struct of metadata to store with the file
* @throwOnMissing Boolean flag to throw if the file is missing. Otherwise it will be created if missing.
*
* @return File
*
* @throws cbfs.FileNotFoundException
*/
function prepend(
   required contents,
   struct metadata        = {},
   boolean throwOnMissing = false
);

setVisibility

Set the storage visibility of a file. Available options are public, private, readonly or a custom data type the implemented driver can interpret.

/**
* @visibility The storage visibility of the file, available options are `public, private, readonly` or a custom data type the implemented driver can interpret
*
* @return File
*/
function setVisibility( required string visibility );

size

Returns the size of a file (in bytes). The size may differ from the actual size on the file system due to compression, support for sparse files, or other reasons.

/**
 * @throws cbfs.FileNotFoundException
 */
numeric function size();

stream

This is currently only available when working with a Local Provider disk.

Return a Java stream of the file using non-blocking IO classes. The stream will represent every line in the file so you can navigate through it. This method leverages the cbstreams library used accordingly by implementations (https://www.forgebox.io/view/cbstreams)

/**
 * @return Stream object: See https://apidocs.ortussolutions.com/coldbox-modules/cbstreams/1.1.0/index.html
 */
function stream(){
        arguments.path = getPath();
        return getDisk().stream( argumentCollection=arguments );
};

temporaryURL

Get a temporary URL for the given file.

/**
 * @expiration The number of minutes this url should be valid for. Defaults to 60 minutes
 */
string function temporaryUrl( numeric expiration = 60 );

touch

Create a new empty file if it does not exist.

/**
* @createPath if set to false, expects all parent directories to exist, true will generate necessary directories. Defaults to true.
*
* @return File
*
* @throws cbfs.PathNotFoundException
*/
function touch( boolean createPath = true );

url

Gets the URL of a file.

/**
 * @throws cbfs.FileNotFoundException
 */
string function url();

visibility

Get the storage visibility of a file. The return format can be a string of public, private, readonly or a custom data type the implemented driver can interpret.

/**
* @return String
*/
string function visibility();

Directory Methods

allContents

Get an array listing of all files and directories in a directory using recursion.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @type      Filter the result to only include files, directories, or both. ('file|files', 'dir|directory', 'all'). Default is 'all'
 * @absolute  Local provider only: We return relative disk paths by default. If true, we return absolute paths
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function allContents(
	required directory,
	any filter,
	sort,
	type             = "all",
	boolean absolute = false
);

allContentsMap

Get an array of content from all the files from a specific directory with recursion.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function allContentsMap( required directory, any filter, sort );

allDirectories

Get an array of all directories in a directory using recursion.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @absolute  Local provider only: We return relative disk paths by default. If true, we return absolute paths
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function allDirectories(
	required directory,
	any filter,
	sort,
	boolean absolute = false
);

allFiles

Get an array of all files in a directory using recursion. This is a shortcut to files() with a recursion argument.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @absolute  Local provider only: We return relative disk paths by default. If true, we return absolute paths
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function allFiles(
	required directory,
	any filter,
	sort,
	boolean absolute = false
);

allFilesMap

Get an array of structs of all recursive files in a directory and their appropriate information map: attributes, dateLastModified, directory, link, name, size, etc.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @extended  Default of false produces basic file info, true, produces posix extended info.
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function allFilesMap(
	required directory,
	any filter,
	sort,
	boolean extended = false
);

buildDiskPath

Builds the path on the provided disk from its root + incoming path with normalization, cleanup, and canonicalization.

/**
 * @path The path on the disk to build
 *
 * @return The canonical path on the disk
 */
function buildDiskPath( required string path );

cleanDirectory

Empty the specified directory of all files and folders.

/**
 * @directory      The directory
 * @throwOnMissing Throws an exception if the directory does not exist, defaults to false
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.DirectoryNotFoundException
 */
function cleanDirectory( required directory, boolean throwOnMissing = false );

contents

Get an array listing of all files and directories in a directory.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @recurse   Recurse into subdirectories, default is false
 * @type      Filter the result to only include files, directories, or both. ('file|files', 'dir|directory', 'all'). Default is 'all'
 * @absolute  Local provider only: We return relative disk paths by default. If true, we return absolute paths
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function contents(
	required directory,
	any filter,
	sort,
	boolean recurse  = false,
	type             = "all",
	boolean absolute = false
);

contentsMap

Get an array of content from all the files from a specific directory.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @recurse   Recurse into subdirectories, default is false
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function contentsMap(
	required directory,
	any filter,
	sort,
	boolean recurse = false
);

copyDirectory

Copies a directory to a destination. The 'filter' argument can be a closure and lambda with the format function(path ).

/**
 * @source      The source directory
 * @destination The destination directory
 * @recurse     If true, copies all subdirectories, otherwise only files in the source directory. Default is false.
 * @filter      A string file extension filter to apply like *.jpg or server-*.json or a lambda/closure that receives the file path and should return true to copy it.
 * @createPath  If false, expects all parent directories to exist, true will generate all necessary directories. Default is true.
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.DirectoryNotFoundException - When the source directory does not exist
 */
function copyDirectory(
	required source,
	required destination,
	boolean recurse = false,
	any filter,
	boolean createPath = true
);

createDirectory

Create a new directory.

/**
 * @directory    The directory path to be created
 * @createPath   Create parent directory paths when they do not exist. The default is true
 * @ignoreExists If false, it will throw an error if the directory already exists, else it ignores it if it exists. This should default to true.
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.DirectoryExistsException - If the directory you are trying to create already exists and <code>ignoreExists</code> is false
 */
function createDirectory(
	required directory,
	boolean createPath   = true,
	boolean ignoreExists = true
);

deleteDirectory

Delete one or more directory locations.

/**
 * @directory      The directory or an array of directories
 * @recurse        Recurse the deletion or not, defaults to true
 * @throwOnMissing Throws an exception if the directory does not exist, defaults to false
 *
 * @return A boolean value or a struct of booleans determining if the directory paths got deleted or not.
 *
 * @throws cbfs.DirectoryNotFoundException
 */
boolean function deleteDirectory(
	required string directory,
	boolean recurse        = true,
	boolean throwOnMissing = false
);

directories

Get an array of all directories in a directory.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @recurse   Recurse into subdirectories, default is false
 * @absolute  Local provider only: We return relative disk paths by default. If true, we return absolute paths
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function directories(
	required directory,
	any filter,
	sort,
	boolean recurse  = false,
	boolean absolute = false
);

directoryExists

Validates that a directory does exists.

/**
 * Validate if a directory exists
 *
 * @path The directory to verify
 */
boolean function directoryExists( required string path )

directoryMissing

Validates that a directory does not exists.

/**
 * Validate if a directory exists
 *
 * @path The directory to verify
 */
boolean function directoryExists( required string path )

files

Get an array of all files in a directory.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @recurse   Recurse into subdirectories, default is false
 * @absolute  Local provider only: We return relative disk paths by default. If true, we return absolute paths
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function files(
	required directory,
	any filter,
	sort,
	boolean recurse  = false,
	boolean absolute = false
);

filesMap

Get an array of structs of all files in a directory and their appropriate information map: attributes, dateLastModified, directory, link, name, size, etc.

/**
 * @directory The directory
 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
 * @recurse   Recurse into subdirectories, default is false
 * @extended  Default of false produces basic file info, true, produces posix extended info.
 *
 * @throws cbfs.DirectoryNotFoundException
 */
array function filesMap(
	required directory,
	any filter,
	sort,
	boolean recurse  = false,
	boolean extended = false
);

isDirectory

Returns a boolean determining if a path is a directory or not.

/**
 * @path The directory path
 *
 * @return true if the file is a directory; false if the file does not exist, is not a directory, or it cannot be determined if the file is a directory or not.
 */
boolean function isDirectory( required path );

moveDirectory

Move or rename a directory.

/**
 * @source      The source directory
 * @destination The destination directory
 * @createPath  If false, expects all parent directories to exist, true will generate all necessary directories. Default is true.
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.DirectoryNotFoundException          - When the source does not exist
 */
function moveDirectory(
	required source,
	required destination,
	boolean createPath = true
);

S3 Provider

Leverage the s3 provider to store files in an s3 compatible file-system.

Use the S3 provider to store files within any S3 compatible file storage service such as AWS S3 or Digital Ocean Spaces.

The S3 provider uses the library for all s3 operations.

Keep in mind when using this provider that all file operations result in an outgoing network request from your application. We have utilized various caching techniques to ensure fast operations, but it's good to be mindful of these outgoing requests when working with files and folders.

Configuration

Example

Properties

This provider uses the library under the hood, and any of the properties that can be passed in are available, most of which are documented here.

Property
Type
Default
Description

Bucket Configuration Considerations

File operations, including the setting of permissions on objects within an AWS bucket require both configuration settings to the bucket and to the user account, in order to all CBFS operations.

User Permissions

In the IAM section of the AWS Manager, your user account should, at minimum have an ACL policy that grants them access to all S3 operations on the bucket. Below is an example of a JSON IAM policy which grants an AWS user access to all bucket operations - including encryption and decryption if that feature is enabled on the bucket:

Bucket Permissions

When creating a bucket to be used with CBFS operations, some initial settings need to be configured, in order for the user you created to perform permissions operations on objects within the bucket. For a non-root user account to perform operations, the following changes to the default configuration must be performed:

  1. Enable ACL's in the Permissions > Object Ownership

  2. Edit Permissions > Block Public Access to allow the IAM users to set their own permissions on objects created. If your bucket is private this will allow the explicit settings for those objects to be peformed.

Note that we have disabled the inheritance settings above, which allows new ACL policies to be created on object, but still disables any cross-account ACL settings, for security.

For public buckets, it is also recommended that you complete the Permissions > CORS section to allow access to your objects only from specific domain referrers.

config/ColdBox.cfc
moduleSettings = {
	"cbfs": {
		// The default disk with a reserved name of 'default'
		"defaultDisk" : "myStorage",
		// Register the disks on the system
		"disks"       : {
			// Your default application storage
			"myStorage" : {
				"provider": "S3",
				"properties": {
					"visibility": "public", // can be 'public' or 'private'
					"path": "",
					"accessKey": "",
					"secretKey": "",
					"awsDomain": "digitaloceanspaces.com",
					"awsRegion": "sfo3",
					"defaultBucketName": "myDOSpace"
				}
			}
		}
	},
};

autoContentType

boolean

false

autoMD5

boolean

false

accessKey

string

--

Your S3 access key

awsDomain

string

--

The domain name used to connect to your s3 service provider

awsRegion

string

--

The region name used to connect to your s3 service provider. Be sure your region is all lowercase, otherwise issues with pre-signed URLs can occur.

cacheLookups

boolean

true

debug

boolean

false

defaultTimeout

numeric

300

The default timeout of the http operations

defaultDelimiter

string

/

Default delimiter to use

defaultBucketName

string

--

The bucket name, within which this disk operates.

defaultCacheControl

string

no-store, no-cache, must-revalidate

defaultStorageClass

string

STANDARD

secretKey

string

--

Your S3 secret key

defaultACL

string

public-read

encryptionCharset

string

UTF-8

The encoding characterset

publicDomain

string

--

Will be the public domain in URLs generated - for example, when using a CDN distribution via CloudFront

retriesOnError

numeric

3

serviceName

string

s3

signatureType

string

v4

Which signature encoding to use, v4 is the latest.

ssl

boolean

true

Use SSL for all operations

throwOnRequestError

boolean

true

uploadMimeAccept

string

*

The mime types which are accepted via the upload method. Defaults to all.

visibility

string

public

Whether the contents of the disk are public (world read ) or private

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1412062044000",
            "Effect": "Allow",
            "Action": [
                "s3:*",
                "kms:Decrypt",
                "kms:Encrypt",
                "kms:GenerateDataKey"
            ],
            "Resource": [
                "arn:aws:s3:::my-bucket-name",
                "arn:aws:s3:::my-bucket-name/*"
            ]
        },
        {
	    "Sid": "AllowListAllBuckets",
	    "Effect": "Allow",
	    "Action": "s3:ListAllMyBuckets",
	    "Resource": "*"
	}
    ]
}
s3sdk
s3sdk

Disk Usage

A collection of functionality for all disks

Configuration Methods

File Methods

Directory Methods

Utility Methods

Stream Methods

Verification Methods

Stream Methods

The stream methods are only available for the LocalProvider currently.

stream

Returns a Java stream of the file using non-blocking IO classes. The stream will represent every line in the file so you can navigate through it.

/**
 * @path The path to read all the files with
 *
 * @return Stream object: See https://apidocs.ortussolutions.com/coldbox-modules/cbstreams/1.1.0/index.html
 */
function stream( required path );

// Example
disk.stream( expandPath( "datadump.txt" ) );

streamOf

Create a Java stream of the incoming array of files or directories.

/**
 * @target The target array of files/directories to generate a stream of
 *
 * @return Stream object: See https://apidocs.ortussolutions.com/coldbox-modules/cbstreams/1.1.0/index.html
 */
function streamOf( required array target ){
	
// Example
disk.streamOf( disk.files( "my.path" ) )
	.filter( function( item ){
		return item.startsWith( "a" );
	} )
	.forEach( function( item ){
		writedump( item );	
	} );

Custom Providers

Learn how to build your own storage providers

You can implement your own custom Disk Provider into your applications by extending cbfs.models.AbstractDiskProvider and creating a provider which includes all of the methods listed in the sample component below:

component extends="cbfs.models.AbstractDiskProvider"{

	/**
	 * Get the unique UUID identifier for this disk
	 */
	string function getIdentifier();

	/**
	 * Returns true if the disk has been started up, false if not.
	 */
	boolean function hasStarted();

	/**
	 * Returns the name of the disk.
	 */
	string function getName();

	/**
	 * Retrieves the settings for the disk.
	 */
	struct function getProperties();

	/**
	 * Startup a disk provider with the instance data it needs to startup. It needs to make sure
	 * that it sets the "started" variable to true in order to operate.
	 *
	 * @name       The name of the disk
	 * @properties A struct of configuration data for this provider, usually coming from the configuration file
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 */
	any function startup( required string name, struct properties = {} );

	/**
	 * Called before the cbfs module is unloaded, or via reinits. This can be implemented
	 * as you see fit to gracefully shutdown connections, sockets, etc.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 */
	any function shutdown();

	/**
	 * Create a file in the disk
	 *
	 * @path       The file path to use for storage
	 * @contents   The contents of the file to store
	 * @visibility The storage visibility of the file, available options are `public, private, readonly` or a custom data type the implemented driver can interpret
	 * @metadata   Struct of metadata to store with the file
	 * @override   Flag to overwrite the file at the destination, if it exists. Defaults to true.
	 * @mode       Applies to *nix systems. If passed, it overrides the visbility argument and uses these octal values instead
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.FileOverrideException - When a file exists and no override has been provided
	 */
	function create(
		required path,
		required contents,
		string visibility,
		struct metadata,
		boolean overwrite = true,
		string mode
	);

	/**
	 * Uploads a file in to the disk
	 *
	 * @fieldName The file field name
	 * @directory the directory on disk to upload to
	 * @overload  We can overload the default because we can go directly to the disk with the file
	 */
	function upload( required fieldName, required directory );

	/**
	 * Set the storage visibility of a file, available options are `public, private, readonly` or a custom data type the implemented driver can interpret
	 *
	 * @path       The target file
	 * @visibility The storage visibility of the file, available options are `public, private, readonly` or a custom data type the implemented driver can interpret
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	any function setVisibility( required string path, required string visibility );

	/**
	 * Get the storage visibility of a file, the return format can be a string of `public, private, readonly` or a custom data type the implemented driver can interpret.
	 *
	 * @path The target file
	 *
	 * @return The visibility of the requested file
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	string function visibility( required string path );

	/**
	 * Prepend contents to the beginning of a file. If the file is missing and the throwOnMissing if false
	 * We will create the file with the contents provided.
	 *
	 * @path           The file path to use for storage
	 * @contents       The contents of the file to prepend
	 * @metadata       Struct of metadata to store with the file
	 * @throwOnMissing Boolean flag to throw if the file is missing. Otherwise it will be created if missing.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	any function prepend(
		required string path,
		required contents,
		struct metadata,
		boolean throwOnMissing
	);

	/**
	 * Append contents to the end of a file. If the file is missing and the throwOnMissing if false
	 * We will create the file with the contents provided.
	 *
	 * @path           The file path to use for storage
	 * @contents       The contents of the file to append
	 * @metadata       Struct of metadata to store with the file
	 * @throwOnMissing Boolean flag to throw if the file is missing. Otherwise it will be created if missing.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	any function append(
		required string path,
		required contents,
		struct metadata,
		boolean throwOnMissing
	);

	/**
	 * Copy a file from one destination to another
	 *
	 * @source      The source file path
	 * @destination The end destination path
	 * @override    Flag to overwrite the file at the destination, if it exists. Defaults to true.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	any function copy(
		required source,
		required destination,
		boolean overwrite = true
	);

	/**
	 * Move a file from one destination to another
	 *
	 * @source      The source file path
	 * @destination The end destination path
	 * @override    Flag to overwrite the file at the destination, if it exists. Defaults to true.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	any function move(
		required source,
		required destination,
		boolean overwrite = true
	);

	/**
	 * Get the contents of a file
	 *
	 * @path The file path to retrieve
	 *
	 * @return The contents of the file
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	any function get( required path );

	/**
	 * Get the contents of a file as binary, such as an executable or image
	 *
	 * @path The file path to retrieve
	 *
	 * @return A binary representation of the file
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	any function getAsBinary( required path );

	/**
	 * Validate if a file/directory exists
	 *
	 * @path The file/directory path to verify
	 */
	boolean function exists( required string path );

	/**
	 * Validate if a file/directory doesn't exist
	 *
	 * @path The file/directory path to verify
	 */
	boolean function missing( required string path );

	/**
	 * Delete a file or an array of file paths. If a file does not exist a `false` will be
	 * shown for it's return.
	 *
	 * @path           A single file path or an array of file paths
	 * @throwOnMissing Boolean to throw an exception if the file is missing.
	 *
	 * @return boolean or struct report of deletion
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	boolean function delete( required any path, boolean throwOnMissing );

	/**
	 * Create a new empty file if it does not exist
	 *
	 * @path       The file path
	 * @createPath if set to false, expects all parent directories to exist, true will generate necessary directories. Defaults to true.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.PathNotFoundException
	 */
	function touch( required path, boolean createpath );

	/**************************************** UTILITY METHODS ****************************************/

	/**
	 * Get the full url for the given file
	 *
	 * @path The file path to build the uri for
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	string function url( required string path )

	/**
	 * Get the URI for the given file
	 *
	 * @path The file path to build the URI for
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	string function uri( required string path );

	/**
	 * Retrieve the size of the file in bytes
	 *
	 * @path The file path location
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	numeric function size( required path );

	/**
	 * Retrieve the file's last modified timestamp
	 *
	 * @path The file path location
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	function lastModified( required path );

	/**
	 * Retrieve the file's mimetype
	 *
	 * @path The file path location
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	function mimeType( required path );

	/**
	 * Return information about the file.  Will contain keys such as lastModified, size, path, name, type, canWrite, canRead, isHidden and more
	 *
	 * @path The file path
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	struct function info( required path );

	/**
	 * Generate checksum for a file in different hashing algorithms
	 *
	 * @path      The file path
	 * @algorithm Default is MD5, but SHA-1, SHA-256, and SHA-512 can also be used.
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	string function checksum( required path, algorithm );

	/**
	 * Extract the file name from a file path
	 *
	 * @path The file path
	 */
	string function name( required path );

	/**
	 * Extract the extension from the file path
	 *
	 * @path The file path
	 */
	string function extension( required path );

	/**
	 * Sets the access attributes of the file on Unix based disks
	 *
	 * @path The file path
	 * @mode Access mode, the same attributes you use for the Linux command `chmod`
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 */
	function chmod( required string path, required string mode );

	/**
	 * Create a symbolic link in the system if it supports it.
	 *
	 * The target parameter is the target of the link. It may be an absolute or relative path and may not exist. When the target is a relative path then file system operations on the resulting link are relative to the path of the link.
	 *
	 * @link   The path of the symbolic link to create
	 * @target The target of the symbolic link
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws UnsupportedOperationException - if the implementation does not support symbolic links
	 */
	function createSymbolicLink( required link, required target );

	/**************************************** VERIFICATION METHODS ****************************************/

	/**
	 * Verifies if the passed path is an existent file
	 *
	 * @path The file path
	 *
	 * @throws cbfs.FileNotFoundException
	 */
	boolean function isFile( required path );

	/**
	 * Is the file writable or not
	 *
	 * @path The file path
	 *
	 * @throws cbfs.FileNotFoundException - If the filepath is missing
	 */
	boolean function isWritable( required path );

	/**
	 * Is the file readable or not
	 *
	 * @path The file path
	 *
	 * @throws cbfs.FileNotFoundException - If the filepath is missing
	 */
	boolean function isReadable( required path );

	/**
	 * Is the file executable or not
	 *
	 * @path The file path
	 *
	 * @throws cbfs.FileNotFoundException - If the filepath is missing
	 */
	boolean function isExecutable( required path );

	/**
	 * Is the file is hidden or not
	 *
	 * @path The file path
	 *
	 * @throws cbfs.FileNotFoundException - If the filepath is missing
	 */
	boolean function isHidden( required path );

	/**
	 * Is the file is a symbolic link
	 *
	 * @path The file path
	 *
	 * @throws cbfs.FileNotFoundException - If the filepath is missing
	 */
	boolean function isSymbolicLink( required path );

	/**************************************** STREAM METHODS ****************************************/

	/**
	 * Return a Java stream of the file using non-blocking IO classes. The stream will represent every line in the file so you can navigate through it.
	 * This method leverages the `cbstreams` library used accordingly by implementations (https://www.forgebox.io/view/cbstreams)
	 *
	 * @path
	 *
	 * @return Stream object: See https://apidocs.ortussolutions.com/coldbox-modules/cbstreams/1.1.0/index.html
	 */
	function stream( required path );

	/**
	 * Create a Java stream of the incoming array of files/directories usually called from this driver as well.
	 * <pre>
	 * disk.streamOf( disk.files( "my.path" ) )
	 * 	.filter( function( item ){
	 *		return item.startsWith( "a" );
	 *	} )
	 *	.forEach( function( item ){
	 *		writedump( item );
	 *	} );
	 * </pre>
	 *
	 * @target The target array of files/directories to generate a stream of
	 *
	 * @return Stream object: See https://apidocs.ortussolutions.com/coldbox-modules/cbstreams/1.1.0/index.html
	 */
	function streamOf( required array target );

	/**************************************** DIRECTORY METHODS ****************************************/

	/**
	 * Is the path a directory or not
	 *
	 * @path The directory path
	 *
	 * @throws cbfs.DirectoryNotFoundException - If the directory path is missing
	 */
	boolean function isDirectory( required path );

	/**
	 * Create a new directory
	 *
	 * @directory    The directory path to be created
	 * @createPath   Create parent directory paths when they do not exist. The default is true
	 * @ignoreExists If false, it will throw an error if the directory already exists, else it ignores it if it exists. This should default to true.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws DirectoryExistsException - If the directory you are trying to create already exists and <code>ignoreExists</code> is true
	 */
	function createDirectory(
		required directory,
		boolean createPath   = true,
		boolean ignoreExists = true
	);

	/**
	 * Copies a directory to a destination
	 *
	 * The `filter` argument can be a closure and lambda with the following format
	 * <pre>
	 * boolean:function( path )
	 * </pre>
	 *
	 * @source      The source directory
	 * @destination The destination directory
	 * @recurse     If true, copies all subdirectories, otherwise only files in the source directory. Default is false.
	 * @filter      A string file extension filter to apply like *.jpg or server-*.json or a lambda/closure that receives the file path and should return true to copy it.
	 * @createPath  If false, expects all parent directories to exist, true will generate all necessary directories. Default is true.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.DirectoryNotFoundException - When the source does not exist
	 */
	function copyDirectory(
		required source,
		required destination,
		boolean recurse = false,
		any filter,
		boolean createPath = true
	);

	/**
	 * Move a directory
	 *
	 * @source      The source directory
	 * @destination The destination directory
	 * @createPath  If false, expects all parent directories to exist, true will generate all necessary directories. Default is true.
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.DirectoryNotFoundException - When the old path does not exist
	 */
	function moveDirectory(
		required source,
		required destination,
		boolean createPath = true
	);

	/**
	 * Delete 1 or more directory locations
	 *
	 * @directory      The directory or an array of directories
	 * @recurse        Recurse the deletion or not, defaults to true
	 * @throwOnMissing Throws an exception if the directory does not exist, defaults to false
	 *
	 * @return A boolean value or a struct of booleans determining if the directory paths got deleted or not.
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	boolean function deleteDirectory(
		required string directory,
		boolean recurse,
		boolean throwOnMissing
	);

	/**
	 * Empty the specified directory of all files and folders.
	 *
	 * @directory      The directory
	 * @throwOnMissing Throws an exception if the directory does not exist, defaults to false
	 *
	 * @return cbfs.models.AbstractDiskProvider
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	function cleanDirectory( required directory, boolean throwOnMissing );

	/**
	 * Get an array listing of all files and directories in a directory.
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 * @recurse   Recurse into subdirectories, default is false
	 * @type      Filter the result to only include files, directories, or both. ('file|files', 'dir|directory', 'all'). Default is 'all'
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function contents(
		required directory,
		any filter,
		sort,
		boolean recurse = false,
		type            = "all"
	);

	/**
	 * Get an array listing of all files and directories in a directory using recursion
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 * @type      Filter the result to only include files, directories, or both. ('file|files', 'dir|directory', 'all'). Default is 'all'
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function allContents(
		required directory,
		any filter,
		sort,
		type = "all"
	);

	/**
	 * Get an array of all files in a directory.
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 * @recurse   Recurse into subdirectories, default is false
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function files(
		required directory,
		any filter,
		sort,
		boolean recurse = false
	);

	/**
	 * Get an array of all directories in a directory.
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 * @recurse   Recurse into subdirectories, default is false
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function directories(
		required directory,
		any filter,
		sort,
		boolean recurse = false
	);

	/**
	 * Get an array of all files in a directory using recursion, this is a shortcut to the `files()` with recursion
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function allFiles( required directory, any filter, sort );

	/**
	 * Get an array of all directories in a directory using recursion
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function allDirectories( required directory, any filter, sort );

	/**
	 * Get an array of structs of all files in a directory and their appropriate information map:
	 * - Attributes
	 * - DateLastModified
	 * - Directory
	 * - Link
	 * - Mode
	 * - Name
	 * - Size
	 * - etc
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 * @recurse   Recurse into subdirectories, default is false
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function filesMap(
		required directory,
		any filter,
		sort,
		boolean recurse = false
	);

	/**
	 * Get an array of structs of all files in a directory with recursion and their appropriate information map:
	 * - Attributes
	 * - DateLastModified
	 * - Directory
	 * - Link
	 * - Mode
	 * - Name
	 * - Size
	 * - etc
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function allFilesMap( required directory, any filter, sort );

	/**
	 * Get an array of content from all the files from a specific directory
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 * @recurse   Recurse into subdirectories, default is false
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function contentsMap(
		required directory,
		any filter,
		sort,
		boolean recurse = false
	);

	/**
	 * Get an array of content from all the files from a specific directory with recursion
	 *
	 * @directory The directory
	 * @filter    A string wildcard or a lambda/closure that receives the file path and should return true to include it in the returned array or not.
	 * @sort      Columns by which to sort. e.g. Directory, Size DESC, DateLastModified.
	 *
	 * @throws cbfs.DirectoryNotFoundException
	 */
	array function allContentsMap( required directory, any filter, sort );

	/**
	 * Find path names matching a given globbing pattern
	 *
	 * @pattern The globbing pattern to match
	 */
	array function glob( required pattern );

}

Testing

To create your own provider tests, create a new Spec which extends cbfs.models.testing.AbstractDiskSpec

Within your tests directory you will need to add a file at tests/resources/assets/binary_file.png which will be used to test binary uploads for the provider you create. Example:

omponent extends="cbfs.models.testing.AbstractDiskSpec" {

	// The name of the provider in the test-harness we want to test
	variables.providerName = "MyCustom";
	variables.TEST_PATH    = expandPath( "/tests/storage" );
	// Which features does this disk support for testing
	variables.testFeatures = { symbolicLink : true };

	function beforeAll(){
		if ( directoryExists( variables.TEST_PATH ) ) {
			directoryDelete( variables.TEST_PATH, true );
		}
		super.beforeAll();
	}

	function run(){
		super.run();

		// Localized Suites

		describe( "MyCustom Provider Extended Specs", function(){
			beforeEach( function( currentSpec ){
				disk = getDisk();
			} );

			story( "I want to test some custom function in my provider", function(){
				...
			} );

		} );
	}

	/**
	 * ------------------------------------------------------------
	 * Concrete Expectations that can be implemented by each provider
	 * ------------------------------------------------------------
	 */
	function validateInfoStruct( required info, required disk ){
		expect( info ).toHaveKey( "path,size,name,type,canWrite,canRead,isHidden" );
	}

}

Utility Methods

checksum

Generates a checksum for a file in different hashing algorithms.

/**
 * @path      The file path
 * @algorithm Default is MD5, but SHA-1, SHA-256, and SHA-512 can also be used.
 *
 * @throws cbfs.FileNotFoundException
 */
string function checksum( required path, algorithm = "MD5" );

// Example
disk.checksum( expandPath( "myFile.txt" ), "SHA-256" );

chmod

Sets the access attributes of the file on Unix-based disks.

/**
 * @path The file path
 * @mode Access mode, the same attributes you use for the Linux command `chmod`
 *
 * @return cbfs.models.IDisk
 */
function chmod( required string path, required string mode );

// Example
disk.chmod( expandPath( "myFile.txt" ), "600" );

createSymbolicLink

Creates a symbolic link in the system if it supports it. The target parameter is the target of the link. It may be an absolute or relative path and may not exist. When the target is a relative path, then file system operations on the resulting link are relative to the path of the link.

/**
 * @link   The path of the symbolic link to create
 * @target The target of the symbolic link
 *
 * @return cbfs.models.IDisk
 *
 * @throws cbfs.FileNotFoundException    - if the target does not exist
 * @throws UnsupportedOperationException - if the implementation does not support symbolic links
 */
function createSymbolicLink( required link, required target );

// Example
disk.createSymbolicLink( expandPath( "/symbolicPath" ), expandPath( "/myfolder" ) );

extension

Extract the extension from the file path

/**
 * @path The file path
 */
string function extension( required path );

// Example
disk.extension( someImagePath ); // returns '.jpg';

info

Returns information about the file. Will contain keys such as lastModified, size, path, name, type, canWrite, canRead, isHidden, and more depending on the provider used.

/**
 * @path The file path
 *
 * @return A struct of file metadata according to provider
 *
 * @throws cbfs.FileNotFoundException
 */
struct function info( required path );

// Example
disk.info( expandPath( "myFile.txt" ) );

lastModified

Retrieves the file's last modified timestamp.

/**
 * @path The file path location
 *
 * @throws cbfs.FileNotFoundException
 */
function lastModified( required path );

// Example
disk.lastModified( expandPath( "myFile.txt" ) );

mimeType

Retrieves the file's mimetype.

/**
 * @path The file path location
 *
 * @throws cbfs.FileNotFoundException
 */
function mimeType( required path );

// Example
disk.mimeType( expandPath( "myFile.jpg" ) ); // returns 'image/jpeg'

size

Retrieves the size of the file in bytes.

/**
 * @path The file path location
 *
 * @throws cbfs.FileNotFoundException
 */
numeric function size( required path );

// Example
disk.size( expandPath( "myFile.txt" ) ); // returns 2097152

temporaryUrl

Gets a temporary URI for the given file.

/**
 * @path       The file path to build the url for
 * @expiration The number of minutes this url should be valid for.
 * @responseHeaders A struct of headers to be forced for the HTTP response of GET requests.  Valid options are content-type, content-language, cache-control, content-disposition, content-encoding
 *
 * @throws cbfs.FileNotFoundException
 */
string function temporaryUrl( required path, numeric expiration, struct responseHeaders );

// Example
disk.temporaryUrl( expandPath( "myFile.txt", 60 ) );

With the S3 provider, you can specify a struct of response headers to control the URL constructed. For example, to generate a URL that ensures a file is returned with the MIME type 'text/plain', you could pass that into temporaryURL().

disk.temporaryURL( path="somefile.txt", expiration=60, responseHeaders= {
    "content-type": "text/plain"
} );

# All arguments
disk.temporaryURL( path="somefile.txt", expiration=60, responseHeaders= {
    "content-type"        : "custom-type",
    "content-language"    : "custom-language",
    "cache-control"       : "custom-cache",
    "content-disposition" : "custom-disposition",
    "content-encoding"    : "custom-encoding"
} );

url

Retrives the full url for a resource

/**
 * Get the full url for the given file
 *
 * @path The file path to build the uri for
 *
 * @throws cbfs.FileNotFoundException
 */
string function url( required string path )