以下是一个简单的文件夹和文件同步到webdav的Go程序:

package main

import (
    "io/ioutil"
    "log"
    "net/http"
    "os"
    "sync"
    "time"

    "github.com/studio-b12/gowebdav"
)

const (
    localPath  = "./download"
    remotePath = "/remote/path"
    logFile    = "./sync.log"
)

func main() {
    // 创建一个webdav客户端
    client := gowebdav.NewClient("https://webdav.example.com", "username", "password")

    // 创建一个日志文件
    f, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
    if err != nil {
        log.Fatalf("无法创建日志文件: %v", err)
    }
    defer f.Close()

    // 定义一个互斥锁来保证日志文件的同步写入
    var mu sync.Mutex

    // 定期扫描本地目录是否有新的文件夹或文件
    ticker := time.NewTicker(100 * time.Millisecond)
    defer ticker.Stop()

    for range ticker.C {
        files, err := ioutil.ReadDir(localPath)
        if err != nil {
            log.Printf("无法读取本地目录: %v", err)
            continue
        }

        for _, file := range files {
            if file.IsDir() {
                // 如果是文件夹,检查远程路径是否存在,不存在则创建
                remoteDir := remotePath + "/" + file.Name()

                _, err := client.Stat(remoteDir)
                if err != nil {
                    if os.IsNotExist(err) {
                        err := client.Mkdir(remoteDir, 0755)
                        if err != nil {
                            log.Printf("无法创建远程文件夹 %s: %v", remoteDir, err)
                            continue
                        }
                    } else {
                        log.Printf("无法访问远程文件夹 %s: %v", remoteDir, err)
                        continue
                    }
                }

                // 如果远程路径存在,则递归同步文件夹内的文件
                syncDir(client, mu, localPath+"/"+file.Name(), remoteDir)
            } else {
                // 如果是文件,启动一个协程并发上传
                go func(client *gowebdav.Client, mu *sync.Mutex, localPath, remotePath string) {
                    // 读取本地文件
                    data, err := ioutil.ReadFile(localPath)
                    if err != nil {
                        log.Printf("无法读取本地文件 %s: %v", localPath, err)
                        return
                    }

                    // 上传文件到远程路径
                    err = client.Write(remotePath, data, 0644)
                    if err != nil {
                        log.Printf("无法上传文件 %s 到远程路径 %s: %v", localPath, remotePath, err)
                        return
                    }

                    // 删除本地文件
                    err = os.Remove(localPath)
                    if err != nil {
                        log.Printf("无法删除本地文件 %s: %v", localPath, err)
                        return
                    }

                    // 更新日志文件
                    mu.Lock()
                    defer mu.Unlock()

                    _, err = f.WriteString(time.Now().Format("2006-01-02 15:04:05") + " 上传文件 " + localPath + " 到 " + remotePath + "\n")
                    if err != nil {
                        log.Printf("无法写入日志文件: %v", err)
                        return
                    }
                }(client, &mu, localPath+"/"+file.Name(), remotePath+"/"+file.Name())
            }
        }
    }
}

func syncDir(client *gowebdav.Client, mu sync.Mutex, localPath, remotePath string) {
    files, err := ioutil.ReadDir(localPath)
    if err != nil {
        log.Printf("无法读取本地目录 %s: %v", localPath, err)
        return
    }

    for _, file := range files {
        if file.IsDir() {
            // 如果是文件夹,检查远程路径是否存在,不存在则创建
            remoteDir := remotePath + "/" + file.Name()

            _, err := client.Stat(remoteDir)
            if err != nil {
                if os.IsNotExist(err) {
                    err := client.Mkdir(remoteDir, 0755)
                    if err != nil {
                        log.Printf("无法创建远程文件夹 %s: %v", remoteDir, err)
                        continue
                    }
                } else {
                    log.Printf("无法访问远程文件夹 %s: %v", remoteDir, err)
                    continue
                }
            }

            // 如果远程路径存在,则递归同步文件夹内的文件
            syncDir(client, mu, localPath+"/"+file.Name(), remoteDir)
        } else {
            // 如果是文件,启动一个协程并发上传
            go func(client *gowebdav.Client, mu *sync.Mutex, localPath, remotePath string) {
                // 读取本地文件
                data, err := ioutil.ReadFile(localPath)
                if err != nil {
                    log.Printf("无法读取本地文件 %s: %v", localPath, err)
                    return
                }

                // 上传文件到远程路径
                err = client.Write(remotePath, data, 0644)
                if err != nil {
                    log.Printf("无法上传文件 %s 到远程路径 %s: %v", localPath, remotePath, err)
                    return
                }

                // 删除本地文件
                err = os.Remove(localPath)
                if err != nil {
                    log.Printf("无法删除本地文件 %s: %v", localPath, err)
                    return
                }

                // 更新日志文件
                mu.Lock()
                defer mu.Unlock()

                _, err = f.WriteString(time.Now().Format("2006-01-02 15:04:05") + " 上传文件 " + localPath + " 到 " + remotePath + "\n")
                if err != nil {
                    log.Printf("无法写入日志文件: %v", err)
                    return
                }
            }(client, &mu, localPath+"/"+file.Name(), remotePath+"/"+file.Name())
        }
    }
}

注意事项:

  • 为了避免重复上传,程序会在上传成功后自动删除本地文件。
  • 更新日志文件的操作需要使用互斥锁来保证同步写入,否则可能会出现多个协程同时写入导致日志文件损坏的情况。
  • 程序中使用了定时器来定期扫描本地目录是否有新的文件夹或文件。如果你的本地目录非常大,可以考虑使用文件系统的事件通知机制来实现实时同步。
给我写一个文件夹和文件同步到webdav的go程序,我的本地目录是download,有新的文件夹或者新的文件,实时同步到webdav,新建一个日志,每一次文件和文件夹上传成功则把日志更新到本地的日志文本当中。0.1秒就扫描一次是否有新的文件夹或者文件,如果有就更新,没有就不更新。文件和文件夹上传的时候并发上传,文件上传成功后自动删除

原文地址: http://www.cveoy.top/t/topic/w6F 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录