Skip to content

Commit

Permalink
Recursive uploads maintain dir structure on server
Browse files Browse the repository at this point in the history
With the use of gowebdav.Mkdir() the UploadDirectory function now
maintains directory structure on the server side.
  • Loading branch information
joereuss12 committed Dec 1, 2023
1 parent 3cc1efd commit 64e4794
Showing 1 changed file with 62 additions and 30 deletions.
92 changes: 62 additions & 30 deletions client/handle_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -300,7 +298,7 @@ func download_http(source string, destination string, payload *payloadStruct, na

if recursive {
var err error
files, err = walkDavDir(&downloadUrl, namespace, token)
files, err = walkDavDir(&downloadUrl, namespace, token, "", false)
if err != nil {
log.Errorln("Error from walkDavDir", err)
return 0, err
Expand Down Expand Up @@ -685,34 +683,31 @@ func (pr *ProgressReader) Close() error {
return err
}

// Recursively uploads a directory with all files and nested dirs, keeping file structure on server side
func UploadDirectory(src string, dest *url.URL, token string, namespace namespaces.Namespace) (int64, error) {
var amountUploaded int64
err := filepath.WalkDir(src, func(path string, info fs.DirEntry, err error) error {
// For now, ignore directories since you cannot PUT a dir
if !(info.IsDir()) {
// Do all this work to update the destination to include the current file at the end
currentDest, err := url.Parse(dest.Path)
if err != nil {
return err
}
baseDir, _ := filepath.Split(currentDest.Path)
newFilename := info.Name()
updatedPath := filepath.Join(baseDir, newFilename)
currentDest.Path = updatedPath
// Upload the file with the updated destination
var uploaded int64
uploaded, err = UploadFile(path, currentDest, token, namespace)
if err != nil {
return err
}
amountUploaded += uploaded
}
return err
})
var files []string
var amountDownloaded int64
srcUrl := url.URL{Path: src}
// Get the list of files as well as make any directories on the server end
files, err := walkDavDir(&srcUrl, namespace, token, dest.Path, true)
if err != nil {
return 0, err
}
return amountUploaded, err

// Upload all of our files within the proper directories
for _, file := range files {
tempDest := url.URL{}
tempDest.Path, err = url.JoinPath(dest.Path, file)
if err != nil {
return 0, err
}
downloaded, err := UploadFile(file, &tempDest, token, namespace)
if err != nil {
return 0, err
}
amountDownloaded += downloaded
}
return amountDownloaded, err
}

// UploadFile Uploads a file using HTTP
Expand Down Expand Up @@ -844,7 +839,7 @@ func doPut(request *http.Request, responseChan chan<- *http.Response, errorChan

}

func walkDavDir(url *url.URL, namespace namespaces.Namespace, token string) ([]string, error) {
func walkDavDir(url *url.URL, namespace namespaces.Namespace, token string, destPath string, upload bool) ([]string, error) {

// Create the client to walk the filesystem
rootUrl := *url
Expand All @@ -869,13 +864,50 @@ func walkDavDir(url *url.URL, namespace namespaces.Namespace, token string) ([]s
// XRootD does not like keep alives and kills things, so turn them off.
transport := config.GetTransport()
c.SetTransport(transport)

files, err := walkDir(url.Path, c)
var files []string
var err error
if upload {
files, err = walkDirUpload(url.Path, c, destPath)
} else {
files, err = walkDir(url.Path, c)
}
log.Debugln("Found files:", files)
return files, err

}

// For uploads, we want to make directories on the server end
func walkDirUpload(path string, client *gowebdav.Client, destPath string) ([]string, error) {
// List of files to return
var files []string
// Whenever this function is called, we should create a new dir on the server side for uploads
err := client.Mkdir(destPath+path, 0755)
if err != nil {
return nil, err
}

// Get our list of files
infos, err := os.ReadDir(path)
if err != nil {
return nil, err
}
for _, info := range infos {
newPath := path + "/" + info.Name()
if info.IsDir() {
// Recursively call this function to create any nested dir's as well as list their files
returnedFiles, err := walkDirUpload(newPath, client, destPath)
if err != nil {
return nil, err
}
files = append(files, returnedFiles...)
} else {
// It is a normal file
files = append(files, newPath)
}
}
return files, err
}

func walkDir(path string, client *gowebdav.Client) ([]string, error) {
var files []string
log.Debugln("Reading directory: ", path)
Expand Down

0 comments on commit 64e4794

Please sign in to comment.