file

package module
v0.0.0-...-c8cbaa3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 15, 2025 License: MIT Imports: 11 Imported by: 0

README

file

file is a simple library that builds on top of io/fs from the Go standard library to provide a simple abstraction for file storage.

Quickstart

file exports the file.Store interface. This interface allows abstracting away the backend for storing files. This library comes with two implementations of this interface, one for storing files on disk, and another for storing files over SFTP.

Below is an example HTTP handler for file uploads,

package main

import (
    "crypto/sha256"
    "net/http"

    "github.com/andrewpillar/file"
    "github.com/andrewpillar/file/disk"
)

const defaultMaxMemory int64 = 32 << 20

func UploadHandler(path string) http.HandlerFunc {
    store := disk.New(path)
    store = file.HashStore(disk, sha256.New)

    return func(w http.ResponseWriter, r *http.Request) {
        if err := r.ParseMultipartForm(defaultMaxMemory); err != nil {
            // Handle error.
        }

        hdrs, ok := r.MultipartForm.File["upload"]

        if !ok {
            // Handle error.
        }

        tmp, err := file.New("upload", hdrs[0].Open())

        if err != nil {
            // Handle error.
        }

        // file.New will store the file in TMPDIR if it's too big to store in
        // memory, so make sure we remove it afterwards.
        defer file.Cleanup(tmp)

        if _, err := store.Put(tmp); err != nil {
            // Handle error.
        }
        w.WriteHeader(http.StatusNoContent)
    }
}

In the above example a handler for uploading files is implemented. This creates a new file.Store for storing files on disk via disk.New which is given the location on disk. Then, this store is given to file.HashStore which will store files against their SHA256 content hash.

In the body of the handler itself, we call file.New which turns a given io.ReadCloser into an fs.File which can then be put into the store. There is a deferred call to file.Cleanup which will delete the file if it was stored on disk as a temporary file from the file.New call.

Finally, we store the file on disk via store.Put.

This library allows for lots of flexibility when it comes to working with files because of the file.Store interface that operates on the fs.File interface. This means additional storage backends can be developed, along with different file representations.

File Store

The core of this library is in the file.Store interface. This interface wraps 6 methods,

the above methods means that the file.Store also implements the following interfaces from the standard library,

Composition

Store composition allows you to combine multiple stores on top of one another. This can be used to change how the file is stored in the backend. For example, a limit can be placed on the size of the files that are stored via the LimitedStore.

store := disk.New(".")
store = file.LimitedStore(store, 5<<20)

With the above example the disk store is passed to the LimitedStore which will limit the files that can be put in the backend to 5MB. If any file exceeds this then an error will be returned.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrReadOnly = errors.New("read only")
View Source
var ErrWriteOnly = errors.New("write only")

Functions

func Cleanup

func Cleanup(f fs.File)

Cleanup removes the given file if it was a temporary file stored on disk that was created via a call to New.

func New

func New(name string, rc io.ReadCloser) (fs.File, error)

New takes the given io.ReadCloser and turns it into an [io.fs.File] with the given name. The contents of the ReadCloser is read into memory. If the size of the data read exceeds 32MB, then a temporary file is created to store the contents. If the ReadCloser is actually an os.File, then no content is read, and the fs.File is returned with the given name.

Types

type MaxSizeError

type MaxSizeError int64

func (MaxSizeError) Error

func (e MaxSizeError) Error() string

type Store

type Store interface {
	// Open opens the named file.
	Open(name string) (fs.File, error)

	// Put stores the given file in the underlying storage backend. This
	// returns the newly stored file. The returned file should be reset to the
	// starting position for reading.
	Put(f fs.File) (fs.File, error)

	// Stat returns the [io.fs.FileInfo] for the named file.
	Stat(name string) (fs.FileInfo, error)

	// Sub returns a new store correspodning with the named dir.
	Sub(dir string) (Store, error)

	// ReadDir reads the named directory and returns the list of entries.
	ReadDir(name string) ([]fs.DirEntry, error)

	// Remove the named file from the backend.
	Remove(name string) error
}

Store represents a storage backend for a file.

This interface implements the [io.fs.FS], [io.fs.SubFS], [io.fs.ReadDirFS], and [io.fs.StatFS] interfaces.

func HashStore

func HashStore(s Store, hash func() hash.Hash) Store

HashStore returns a stoe that will store all files against the given hash of their content.

Any sub stores returned via Sub will also have the files stored agains the given hash of their content.

func LimitedStore

func LimitedStore(s Store, n int64) Store

LimitedStore returns a store that limits the size of files put inside it to n bytes. If any file exceeds this limit then the MaxSizeError is returned.

Any sub stores returned via Sub will also have this limitation imposed upon them.

func ReadOnlyStore

func ReadOnlyStore(s Store) Store

ReadOnlyStore returns a store that prevents any writing. Any calls to Put, or Remove will result in the ErrReadOnly error.

func UniqueStore

func UniqueStore(s Store) Store

UniqueStore returns a store that prevents duplicate files being stored in it. If a duplicate file is placed in the store, then the [io.fs.ErrExist] error is returned.

Any sub stores returned via Sub will also have this limitation imposed upon them.

func WriteOnlyStore

func WriteOnlyStore(s Store) Store

WriteOnlyStore returns a store that prevents any reading. Any calls to Open, Stat, Sub, ReadDir, Remove, will result in the ErrWriteOnly error.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL