Files
WarpBox/lib/server/files.go

126 lines
3.1 KiB
Go
Raw Normal View History

package server
import (
"archive/zip"
"fmt"
"io"
"mime/multipart"
"os"
"path/filepath"
"github.com/gin-gonic/gin"
"warpbox/lib/models"
)
func listCompletedFilesFromDisk(boxID string) ([]models.BoxFile, error) {
entries, err := os.ReadDir(boxPath(boxID))
if err != nil {
return nil, err
}
files := make([]models.BoxFile, 0, len(entries))
for _, entry := range entries {
if entry.IsDir() || entry.Name() == boxManifestFile {
continue
}
info, err := entry.Info()
if err != nil {
return nil, err
}
name := entry.Name()
mimeType := mimeTypeForFile(filepath.Join(boxPath(boxID), name), name)
files = append(files, decorateBoxFile(boxID, models.BoxFile{
ID: name,
Name: name,
Size: info.Size(),
MimeType: mimeType,
Status: fileStatusReady,
}))
}
return files, nil
}
func addFileToZip(zipWriter *zip.Writer, boxID string, filename string) error {
path := filepath.Join(boxPath(boxID), filename)
source, err := os.Open(path)
if err != nil {
return err
}
defer source.Close()
destination, err := zipWriter.Create(filename)
if err != nil {
return err
}
_, err = io.Copy(destination, source)
return err
}
func saveManifestUploadedFile(ctx *gin.Context, boxID string, fileID string, file *multipart.FileHeader) (models.BoxFile, error) {
boxManifestMu.Lock()
defer boxManifestMu.Unlock()
manifest, err := readBoxManifestUnlocked(boxID)
if err != nil {
return models.BoxFile{}, err
}
fileIndex := -1
for index, manifestFile := range manifest.Files {
if manifestFile.ID == fileID {
fileIndex = index
break
}
}
if fileIndex < 0 {
return models.BoxFile{}, fmt.Errorf("File not found")
}
filename := manifest.Files[fileIndex].Name
if err := os.MkdirAll(boxPath(boxID), 0755); err != nil {
return models.BoxFile{}, fmt.Errorf("Could not prepare upload box")
}
destination := filepath.Join(boxPath(boxID), filename)
if err := ctx.SaveUploadedFile(file, destination); err != nil {
manifest.Files[fileIndex].Status = fileStatusFailed
writeBoxManifestUnlocked(boxID, manifest)
return models.BoxFile{}, fmt.Errorf("Could not save uploaded file")
}
manifest.Files[fileIndex].Size = file.Size
manifest.Files[fileIndex].MimeType = mimeTypeForFile(destination, filename)
manifest.Files[fileIndex].Status = fileStatusReady
if err := writeBoxManifestUnlocked(boxID, manifest); err != nil {
return models.BoxFile{}, err
}
return decorateBoxFile(boxID, manifest.Files[fileIndex]), nil
}
func saveUploadedFile(ctx *gin.Context, boxID string, file *multipart.FileHeader) (gin.H, error) {
filename, ok := safeFilename(file.Filename)
if !ok {
return nil, fmt.Errorf("Invalid filename")
}
boxPath := boxPath(boxID)
if err := os.MkdirAll(boxPath, 0755); err != nil {
return nil, fmt.Errorf("Could not prepare upload box")
}
filename = uniqueFilename(boxPath, filename)
destination := filepath.Join(boxPath, filename)
if err := ctx.SaveUploadedFile(file, destination); err != nil {
return nil, fmt.Errorf("Could not save uploaded file")
}
return gin.H{"name": filename, "size": file.Size}, nil
}