github.com/fzfile/BaiduPCS-Go@v0.0.0-20200606205115-4408961cf336/internal/pcscommand/upload.go (about) 1 package pcscommand 2 3 import ( 4 "fmt" 5 "github.com/fzfile/BaiduPCS-Go/baidupcs" 6 "github.com/fzfile/BaiduPCS-Go/internal/pcsconfig" 7 "github.com/fzfile/BaiduPCS-Go/internal/pcsfunctions/pcsupload" 8 "github.com/fzfile/BaiduPCS-Go/pcstable" 9 "github.com/fzfile/BaiduPCS-Go/pcsutil" 10 "github.com/fzfile/BaiduPCS-Go/pcsutil/checksum" 11 "github.com/fzfile/BaiduPCS-Go/pcsutil/converter" 12 "github.com/fzfile/BaiduPCS-Go/pcsutil/taskframework" 13 "os" 14 "path" 15 "path/filepath" 16 "strings" 17 ) 18 19 const ( 20 // DefaultUploadMaxRetry 默认上传失败最大重试次数 21 DefaultUploadMaxRetry = 3 22 ) 23 24 type ( 25 // UploadOptions 上传可选项 26 UploadOptions struct { 27 Parallel int 28 MaxRetry int 29 NoRapidUpload bool 30 NoSplitFile bool // 禁用分片上传 31 } 32 ) 33 34 // RunRapidUpload 执行秒传文件, 前提是知道文件的大小, md5, 前256KB切片的 md5, crc32 35 func RunRapidUpload(targetPath, contentMD5, sliceMD5, crc32 string, length int64) { 36 err := matchPathByShellPatternOnce(&targetPath) 37 if err != nil { 38 fmt.Printf("警告: %s, 获取网盘路径 %s 错误, %s\n", baidupcs.OperationRapidUpload, targetPath, err) 39 } 40 41 err = GetBaiduPCS().RapidUpload(targetPath, contentMD5, sliceMD5, crc32, length) 42 if err != nil { 43 fmt.Printf("%s失败, 消息: %s\n", baidupcs.OperationRapidUpload, err) 44 return 45 } 46 47 fmt.Printf("%s成功, 保存到网盘路径: %s\n", baidupcs.OperationRapidUpload, targetPath) 48 return 49 } 50 51 // RunCreateSuperFile 执行分片上传—合并分片文件 52 func RunCreateSuperFile(targetPath string, blockList ...string) { 53 err := matchPathByShellPatternOnce(&targetPath) 54 if err != nil { 55 fmt.Printf("警告: %s, 获取网盘路径 %s 错误, %s\n", baidupcs.OperationUploadCreateSuperFile, targetPath, err) 56 } 57 58 err = GetBaiduPCS().UploadCreateSuperFile(true, targetPath, blockList...) 59 if err != nil { 60 fmt.Printf("%s失败, 消息: %s\n", baidupcs.OperationUploadCreateSuperFile, err) 61 return 62 } 63 64 fmt.Printf("%s成功, 保存到网盘路径: %s\n", baidupcs.OperationUploadCreateSuperFile, targetPath) 65 return 66 } 67 68 // RunUpload 执行文件上传 69 func RunUpload(localPaths []string, savePath string, opt *UploadOptions) { 70 if opt == nil { 71 opt = &UploadOptions{} 72 } 73 74 // 检测opt 75 if opt.Parallel <= 0 { 76 opt.Parallel = pcsconfig.Config.MaxUploadParallel 77 } 78 79 if opt.MaxRetry < 0 { 80 opt.MaxRetry = DefaultUploadMaxRetry 81 } 82 83 err := matchPathByShellPatternOnce(&savePath) 84 if err != nil { 85 fmt.Printf("警告: 上传文件, 获取网盘路径 %s 错误, %s\n", savePath, err) 86 } 87 88 switch len(localPaths) { 89 case 0: 90 fmt.Printf("本地路径为空\n") 91 return 92 } 93 94 // 打开上传状态 95 uploadDatabase, err := pcsupload.NewUploadingDatabase() 96 if err != nil { 97 fmt.Printf("打开上传未完成数据库错误: %s\n", err) 98 return 99 } 100 defer uploadDatabase.Close() 101 102 var ( 103 pcs = GetBaiduPCS() 104 // 使用 task framework 105 executor = &taskframework.TaskExecutor{ 106 IsFailedDeque: true, // 失败统计 107 } 108 subSavePath string 109 // 统计 110 statistic = &pcsupload.UploadStatistic{} 111 ) 112 113 statistic.StartTimer() // 开始计时 114 115 for k := range localPaths { 116 walkedFiles, err := pcsutil.WalkDir(localPaths[k], "") 117 if err != nil { 118 fmt.Printf("警告: 遍历错误: %s\n", err) 119 continue 120 } 121 122 for k3 := range walkedFiles { 123 var localPathDir string 124 // 针对 windows 的目录处理 125 if os.PathSeparator == '\\' { 126 walkedFiles[k3] = pcsutil.ConvertToUnixPathSeparator(walkedFiles[k3]) 127 localPathDir = pcsutil.ConvertToUnixPathSeparator(filepath.Dir(localPaths[k])) 128 } else { 129 localPathDir = filepath.Dir(localPaths[k]) 130 } 131 132 // 避免去除文件名开头的"." 133 if localPathDir == "." { 134 localPathDir = "" 135 } 136 137 subSavePath = strings.TrimPrefix(walkedFiles[k3], localPathDir) 138 139 info := executor.Append(&pcsupload.UploadTaskUnit{ 140 LocalFileChecksum: checksum.NewLocalFileChecksum(walkedFiles[k3], int(baidupcs.SliceMD5Size)), 141 SavePath: path.Clean(savePath + baidupcs.PathSeparator + subSavePath), 142 PCS: pcs, 143 UploadingDatabase: uploadDatabase, 144 Parallel: opt.Parallel, 145 NoRapidUpload: opt.NoRapidUpload, 146 NoSplitFile: opt.NoSplitFile, 147 UploadStatistic: statistic, 148 }, opt.MaxRetry) 149 fmt.Printf("[%s] 加入上传队列: %s\n", info.Id(), walkedFiles[k3]) 150 } 151 } 152 153 // 没有添加任何任务 154 if executor.Count() == 0 { 155 fmt.Printf("未检测到上传的文件.\n") 156 return 157 } 158 159 // 执行上传任务 160 executor.Execute() 161 162 fmt.Printf("\n") 163 fmt.Printf("上传结束, 时间: %s, 总大小: %s\n", statistic.Elapsed()/1e6*1e6, converter.ConvertFileSize(statistic.TotalSize())) 164 165 // 输出上传失败的文件列表 166 failedList := executor.FailedDeque() 167 if failedList.Size() != 0 { 168 fmt.Printf("以下文件上传失败: \n") 169 tb := pcstable.NewTable(os.Stdout) 170 for e := failedList.Shift(); e != nil; e = failedList.Shift() { 171 item := e.(*taskframework.TaskInfoItem) 172 tb.Append([]string{item.Info.Id(), item.Unit.(*pcsupload.UploadTaskUnit).LocalFileChecksum.Path}) 173 } 174 tb.Render() 175 } 176 }