Files
arsam 055d864490 Import source: handler/fs/fs
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:18:55 +03:30

85 lines
2.2 KiB
Go

package fs
import (
"io"
"path"
"reactor-crw"
)
// PathResolver defines a simple interface to resolve path for content
// before saving it.
type pathResolver interface {
// CreateFolder creates a new folder in the "current" dir. The current
// directory is specified in Config.SavePath provided by a user. If dir
// with such name already exists it'll skip creation step.
CreateFolder(name string) error
// CreateFile creates a new file for downloaded content in the directory
// created by the CreateFolder function and returns the corresponding
// io.WriteCloser. If a file with such a name already exists then it'll
// be overwritten.
CreateFile(name string) (io.WriteCloser, error)
// Remove removes a file or folder by its name. If provided path does not
// exist it'll be skipped.
Remove(name string)
}
// FileSaver defines ContentHandler implementation that will download content
// and save it to the host's file system. It resolves the corresponding file
// path with PathResolver.
type FileSaver struct {
pr pathResolver
t reactor_crw.Transport
}
// NewFileSaver creates a new FileSaver instance along with a new folder that
// will act as a context for a new instance. All files will be processed within
// this new folder.
func NewFileSaver(pr pathResolver, t reactor_crw.Transport, baseFolder string) (*FileSaver, error) {
err := pr.CreateFolder(baseFolder)
if err != nil {
return nil, err
}
return &FileSaver{
pr: pr,
t: t,
}, nil
}
// Process downloads content by the corresponding URL by making an HTTP request
// and saves the result to the file system. In case of error during saving the
// content the corresponding file will be deleted from the file system.
func (f *FileSaver) Process(url string, progress chan<- int, e chan<- error) {
defer func() {
progress <- 1
}()
data, err := f.t.FetchData(url)
if err != nil {
e <- err
return
}
defer func(b io.ReadCloser) {
_ = b.Close()
}(data)
file, err := f.pr.CreateFile(path.Base(url))
if err != nil {
e <- err
return
}
defer func(f io.WriteCloser) {
_ = f.Close()
}(file)
_, err = io.Copy(file, data)
if err != nil {
f.pr.Remove(path.Base(url))
e <- err
}
}