filemanager

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 1, 2024 License: MIT Imports: 28 Imported by: 1

README

FileManager Package

The FileManager package is a powerful and flexible solution for handling and processing files in Go. It provides a convenient way to manage file storage, retrieval, and processing using a plugin-based architecture.

Features

  • File storage and retrieval: Store and retrieve files from different storage types (public, private, temporary).
  • File processing: Process files using various processing plugins, such as image manipulation, PDF manipulation, and more.
  • Recipe-based processing: Define processing recipes that specify a sequence of processing steps to be applied to files.
  • Upload handling: Handle file uploads and trigger processing recipes based on the uploaded files.

Usage

Initialization

To start using the FileManager package, you need to initialize a new instance of the FileManager struct:

import "github.com/itsatony/go-filemanager"

fm := filemanager.NewFileManager(publicBasePath, privateBasePath, baseURL, tempPath)
  • publicBasePath: The base path for storing public files.
  • privateBasePath: The base path for storing private files.
  • baseURL: The base URL for accessing files.
  • tempPath: The path for storing temporary files.
Adding Processing Plugins

To add processing plugins to the FileManager, use the AddProcessingPlugin method:

fm.AddProcessingPlugin("image_manipulation", &filemanager.ImageManipulationPlugin{})
fm.AddProcessingPlugin("pdf_manipulation", &filemanager.PDFManipulationPlugin{})
fm.AddProcessingPlugin("pdf_text_extractor", &filemanager.PDFTextExtractorPlugin{})
Loading Recipes

To load processing recipes from a directory, use the LoadRecipes method:

err := fm.LoadRecipes("path/to/recipes")
if err != nil {
    // Handle the error
}

The recipe files should be in YAML format and stored in the specified directory.

Processing Files

To process a file using a specific recipe, use the ProcessFile method:

file := &filemanager.ManagedFile{
    FileName: "example.jpg",
    Content:  fileContent,
    MetaData: map[string]interface{}{
        "format": "webp",
        "width":  800,
        "height": 600,
    },
}

statusCh := make(chan filemanager.ProcessingStatus)
go func() {
    fm.ProcessFile(file, "image_processing_recipe", statusCh)
}()

for status := range statusCh {
    if status.Error != nil {
        // Handle the processing error
    } else if status.Done {
        // Processing completed successfully
    } else {
        // Processing progress update
        fmt.Printf("Processing progress: %d%%\n", status.Percentage)
    }
}
Handling File Uploads

To handle file uploads and trigger processing recipes, use the HandleFileUpload method:

In this updated example:

We create a statusCh channel to receive the processing status updates, including upload progress updates. We use a goroutine to handle the file upload asynchronously using the HandleFileUpload function. We pass the fileReader (an io.Reader representing the file data) and the statusCh channel to the function. If an error occurs during the upload, we handle it appropriately. After the file is successfully uploaded, we trigger a processing recipe using the ProcessFile function, passing the uploaded file, the recipe name, and the statusCh channel. We use a for loop to consume the status updates from the statusCh channel. If the status contains an error, we handle it appropriately. If the status indicates that the processing is done (status.Done is true), we handle the completion of the processing. If the status is neither an error nor a completion status, it represents an upload or processing progress update. We print the progress percentage using status.Percentage.

statusCh := make(chan filemanager.ProcessingStatus)
go func() {
    file, err := fm.HandleFileUpload(fileReader, statusCh)
    if err != nil {
        // Handle the upload error
    }
    
    // Trigger a processing recipe
    fm.ProcessFile(file, "upload_processing_recipe", statusCh)
}()

for status := range statusCh {
    if status.Error != nil {
        // Handle the processing error
    } else if status.Done {
        // Processing completed successfully
    } else {
        // Upload or processing progress update
        fmt.Printf("Progress: %d%%\n", status.Percentage)
    }
}

Example Recipes

Here are a few example recipes that demonstrate the usage of different processing plugins:

Image Processing Recipe
name: image_processing_recipe
accepted_mime_types:
  - image/jpeg
  - image/png
min_file_size: 1024
max_file_size: 10485760
processing_steps:
  - plugin_name: image_manipulation
    params:
      format: webp
      width: 800
      height: 600
      aspect_ratio: "4:3"
output_formats:
  - format: webp
    target_file_name: processed_image.webp
    storage_type: public

This recipe processes image files by converting them to WebP format, resizing them to 800x600 pixels, and cropping them to a 4:3 aspect ratio. The processed image is stored as a public file.

PDF Text Extraction Recipe
name: pdf_text_extraction_recipe
accepted_mime_types:
  - application/pdf
min_file_size: 1024
max_file_size: 52428800
processing_steps:
  - plugin_name: pdf_text_extractor
    params:
      output_format: markdown
output_formats:
  - format: md
    target_file_name: extracted_text.md
    storage_type: private

This recipe extracts text from PDF files and converts it to Markdown format. The extracted text is stored as a private file.

Upload Processing Recipe
name: upload_processing_recipe
accepted_mime_types:
  - image/jpeg
  - image/png
  - application/pdf
min_file_size: 1024
max_file_size: 52428800
processing_steps:
  - plugin_name: image_manipulation
    params:
      format: jpg
      width: 1200
      height: 800
  - plugin_name: pdf_manipulation
    params:
      manipulation_type: compress
      compression_level: medium
output_formats:
  - format: jpg
    target_file_name: processed_upload.jpg
    storage_type: public
  - format: pdf
    target_file_name: compressed_upload.pdf
    storage_type: private

This recipe processes uploaded files based on their MIME type. If the uploaded file is an image, it is converted to JPEG format and resized to 1200x800 pixels. If the uploaded file is a PDF, it is compressed using the medium compression level. The processed files are stored as public (for images) and private (for PDFs) files.

Included Plugins / Processors

The FileManager package comes with several built-in plugins and processors that can be used to manipulate and process files. Here's a list and description of the plugins and processors available:

Image Manipulation Plugin

The Image Manipulation plugin allows you to perform various image processing operations on image files. It supports the following parameters:

  • format: The output format of the processed image. Supported formats: "jpg", "png", "webp".
  • width: The desired width of the processed image in pixels.
  • height: The desired height of the processed image in pixels.
  • aspect_ratio: The desired aspect ratio of the processed image. Supported aspect ratios: "1:1", "4:3", "16:9", "21:9".

This plugin can be used to resize, crop, and convert image files to different formats.

PDF Text Extractor Plugin

The PDF Text Extractor plugin allows you to extract text from PDF files and convert it to plain text or Markdown format. It supports the following parameter:

  • output_format: The output format of the extracted text. Supported formats: "text", "markdown".

This plugin is useful for extracting text content from PDF files and converting it to a more readable and editable format.

PDF Manipulation Plugin

The PDF Manipulation plugin allows you to perform various operations on PDF files, such as extracting pages, merging PDFs, compressing PDFs, and reordering pages. It supports the following parameters:

  • manipulation_type: The type of manipulation to perform on the PDF. Supported types: "extract", "merge", "compress", "reorder".
  • start_page (for "extract"): The starting page number to extract (inclusive).
  • end_page (for "extract"): The ending page number to extract (inclusive).
  • merge_files (for "merge"): An array of file names to be merged with the base PDF.
  • compression_level (for "compress"): The compression level to apply. Supported levels: "low", "medium", "high".
  • page_order (for "reorder"): An array of page numbers representing the desired order of pages.

This plugin provides powerful capabilities for manipulating PDF files, such as extracting specific pages, merging multiple PDFs into one, compressing PDFs to reduce file size, and reordering pages.

ClamAV Plugin

The ClamAV plugin allows you to scan files for viruses using the ClamAV antivirus engine. It doesn't require any additional parameters.

This plugin is useful for ensuring the security of uploaded files by scanning them for known viruses and malware using the ClamAV engine.

These plugins and processors can be used individually or chained together in processing recipes to create custom file processing workflows. The FileManager package provides flexibility and extensibility, allowing you to easily add new plugins and processors to meet your specific requirements.

For detailed information on how to use these plugins and processors, please refer to the documentation and examples provided in the README file.

Here's a section for the Format Converter Processor plugin that you can add to the README file, along with an examples section:

Format Converter Processor Plugin

The Format Converter Processor plugin allows you to convert various file formats into text-based versions suitable for further processing or injection into Large Language Models (LLMs). It currently supports the following file format conversions:

  • DOCX to plain text
  • DOCX to Markdown
  • Excel (XLS, XLSX) to CSV

The plugin uses the following libraries for file format conversions:

  • github.com/yuin/goldmark for DOCX to Markdown conversion
  • github.com/360EntSecGroup-Skylar/excelize/v2 for Excel to CSV conversion
Limitations
  • The DOCX to plain text conversion is currently a placeholder implementation that assumes the content is already in plain text format. You may need to replace it with a custom implementation or a library that converts DOCX to plain text.
  • The Excel to CSV conversion currently converts only the first sheet of the Excel file. If you need to handle multiple sheets or specify a specific sheet, you may need to modify the convertExcelToCSV function accordingly.

Please refer to the plugin's source code for more details on its implementation and functionality.

Exif Metadata Extractor Plugin

The Exif Metadata Extractor plugin allows you to extract Exif metadata from image files. It retrieves information such as camera make, model, capture date and time, GPS coordinates, focal length, aperture, exposure time, and ISO speed ratings.

The plugin uses the following library for Exif metadata extraction:

  • github.com/rwcarlsen/goexif/exif for extracting Exif metadata from image files
Exif Metadata Extractor Usage

To use the Exif Metadata Extractor plugin, include it in your processing pipeline by adding the following configuration to your recipe:

processing_steps:
  - plugin_name: exif_metadata_extractor

The plugin will automatically detect image files based on their MIME type and extract the Exif metadata.

Versions

  • v0.1.2: Minor updates and improvements to the FileManager package. Added a processor plugin for file-format conversion of .docx and .xlsx to text, markdown and csv. added exif metadata extraction processor.
  • v0.1.0: Initial release with basic file storage and retrieval functionality. File Upload handling and recipe-based processing with a few example recipes and processor plugins.

Installation

To use the FileManager package in your Go project, you need to install it using the following command:

go get github.com/itsatony/go-filemanager

Contributing

Contributions to the FileManager package are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request on the GitHub repository.

License

The FileManager package is open-source software licensed under the MIT License.

Documentation

Overview

file_manager.go

processing.go

upload.go

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrRecipeNotFound           = errors.New("recipe not found")
	ErrInvalidMimeType          = errors.New("invalid MIME type")
	ErrInvalidFileSize          = errors.New("invalid file size")
	ErrProcessingPluginNotFound = errors.New("processing plugin not found")
)
View Source
var ErrLocalFileNotFound = errors.New("local file not found")
View Source
var ErrUrlNotMapped = errors.New("url not mapped to local file")

Functions

func DownloadFileFromUrl

func DownloadFileFromUrl(url string, localFilePath string) (err error)

func FileExists

func FileExists(filePath string) bool

func GuessMimeType

func GuessMimeType(filepath string) (string, error)

Types

type ClamAVPlugin

type ClamAVPlugin struct {
	// contains filtered or unexported fields
}

func NewClamAVPlugin

func NewClamAVPlugin(tcpConnection string) (*ClamAVPlugin, error)

NewClamAVPlugin creates a new ClamAVPlugin instance - only works with TCP connection tcp := viper.GetString("CLAMAV_TCP")

func (*ClamAVPlugin) Process

func (p *ClamAVPlugin) Process(files []*ManagedFile) ([]*ManagedFile, error)

type ExifMetadataExtractorPlugin added in v0.1.2

type ExifMetadataExtractorPlugin struct{}

func (*ExifMetadataExtractorPlugin) Process added in v0.1.2

func (p *ExifMetadataExtractorPlugin) Process(files []*ManagedFile) ([]*ManagedFile, error)

type FileManager

type FileManager struct {
	// contains filtered or unexported fields
}

func NewFileManager

func NewFileManager(publicLocalBasePath, privateLocalBasePath, baseUrl, tempPath string) *FileManager

func (*FileManager) AddProcessingPlugin

func (fm *FileManager) AddProcessingPlugin(name string, plugin ProcessingPlugin)

func (*FileManager) GetBaseUrl

func (aifm *FileManager) GetBaseUrl() string

func (*FileManager) GetLocalPathForFile

func (aifm *FileManager) GetLocalPathForFile(target FileStorageType, filename string) string

func (*FileManager) GetLocalPathOfUrl

func (aifm *FileManager) GetLocalPathOfUrl(url string) (localPath string, err error)

func (*FileManager) GetLocalTemporaryFilePath

func (aifm *FileManager) GetLocalTemporaryFilePath(fileName string) string

func (*FileManager) GetLocalTemporaryPath

func (aifm *FileManager) GetLocalTemporaryPath() string

func (*FileManager) GetPrivateLocalBasePath

func (aifm *FileManager) GetPrivateLocalBasePath() string

func (*FileManager) GetPrivateLocalFilePath

func (aifm *FileManager) GetPrivateLocalFilePath(fileName string) string

func (*FileManager) GetPublicLocalBasePath

func (aifm *FileManager) GetPublicLocalBasePath() string

func (*FileManager) GetPublicLocalFilePath

func (aifm *FileManager) GetPublicLocalFilePath(fileName string) string

func (*FileManager) GetPublicUrlForFile

func (aifm *FileManager) GetPublicUrlForFile(localFilePath string) (url string, err error)

func (*FileManager) HandleFileUpload

func (fm *FileManager) HandleFileUpload(r io.Reader, statusCh chan<- ProcessingStatus) (*ManagedFile, error)

func (*FileManager) LoadRecipes

func (fm *FileManager) LoadRecipes(recipesDir string) error

func (*FileManager) ProcessFile

func (fm *FileManager) ProcessFile(file *ManagedFile, recipeName string, statusCh chan<- ProcessingStatus)

type FileStorageType

type FileStorageType string
const (
	FileStorageTypePrivate FileStorageType = "private"
	FileStorageTypeTemp    FileStorageType = "temp"
	FileStorageTypePublic  FileStorageType = "public"
)

type FormatConverterPlugin added in v0.1.2

type FormatConverterPlugin struct{}

func (*FormatConverterPlugin) Process added in v0.1.2

func (p *FormatConverterPlugin) Process(files []*ManagedFile) ([]*ManagedFile, error)

type ImageManipulationPlugin

type ImageManipulationPlugin struct{}

func (*ImageManipulationPlugin) Process

func (p *ImageManipulationPlugin) Process(files []*ManagedFile) ([]*ManagedFile, error)

type ManagedFile

type ManagedFile struct {
	FileName         string         `json:"fileName"`
	MimeType         string         `json:"mimetype"`
	URL              string         `json:"url"`
	LocalFilePath    string         `json:"localFilePath"`
	FileSize         int64          `json:"fileSize"`
	MetaData         map[string]any `json:"metaData"`
	ProcessingErrors []string       `json:"processingErrors"`
	Content          []byte         `json:"-"`
}

func (*ManagedFile) EnsureFileIsLocal

func (entity *ManagedFile) EnsureFileIsLocal(fm *FileManager, target FileStorageType) (file *ManagedFile, err error)

func (*ManagedFile) EnsurePublicURL

func (entity *ManagedFile) EnsurePublicURL(fm *FileManager) (pubUrl string, err error)

func (*ManagedFile) GetFileName

func (entity *ManagedFile) GetFileName() string

func (*ManagedFile) GetLocalFilePathWithoutFileName

func (entity *ManagedFile) GetLocalFilePathWithoutFileName() string

func (*ManagedFile) GetMetaData

func (entity *ManagedFile) GetMetaData(key string) (value any)

func (*ManagedFile) Save

func (file *ManagedFile) Save() error

func (*ManagedFile) SetMetaData

func (entity *ManagedFile) SetMetaData(key string, value any)

func (*ManagedFile) UpdateFilesize

func (entity *ManagedFile) UpdateFilesize() int64

func (*ManagedFile) UpdateMimeType

func (entity *ManagedFile) UpdateMimeType() string

type OutputFormat

type OutputFormat struct {
	Format         string          `yaml:"format"`
	TargetFileName string          `yaml:"targetFileName"`
	StorageType    FileStorageType `yaml:"storageType"` // public, private, temp
}

type PDFManipulationPlugin

type PDFManipulationPlugin struct{}

func (*PDFManipulationPlugin) Process

func (p *PDFManipulationPlugin) Process(files []*ManagedFile) ([]*ManagedFile, error)

type PDFTextExtractorPlugin

type PDFTextExtractorPlugin struct{}

func (*PDFTextExtractorPlugin) Process

func (p *PDFTextExtractorPlugin) Process(files []*ManagedFile) ([]*ManagedFile, error)

type ProcessingPlugin

type ProcessingPlugin interface {
	Process(files []*ManagedFile) ([]*ManagedFile, error)
}

type ProcessingStatus

type ProcessingStatus struct {
	Percentage int
	Error      error
	Done       bool
}

type ProcessingStep

type ProcessingStep struct {
	PluginName string         `yaml:"pluginName"`
	Params     map[string]any `yaml:"params"`
}

type ProgressReader

type ProgressReader struct {
	Reader   io.Reader
	Size     int64
	Uploaded int64
	StatusCh chan<- ProcessingStatus
}

func (*ProgressReader) Read

func (r *ProgressReader) Read(p []byte) (int, error)

type Recipe

type Recipe struct {
	Name              string           `yaml:"name"`
	AcceptedMimeTypes []string         `yaml:"acceptedMimeTypes"`
	MinFileSize       int64            `yaml:"minFileSize"`
	MaxFileSize       int64            `yaml:"maxFileSize"`
	ProcessingSteps   []ProcessingStep `yaml:"processingSteps"`
	OutputFormats     []OutputFormat   `yaml:"outputFormats"`
}

Jump to

Keyboard shortcuts

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