github.com/qiniu/go-sdk/v7@v7.27.0/storage/bucket_list.go (about) 1 package storage 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/url" 8 "strconv" 9 10 "github.com/qiniu/go-sdk/v7/auth" 11 ) 12 13 // ListItem 为文件列举的返回值 14 type ListItem struct { 15 // 资源名 16 Key string `json:"key"` 17 18 // 上传时间,单位:100纳秒,其值去掉低七位即为Unix时间戳。 19 PutTime int64 `json:"putTime"` 20 21 // 文件的HASH值,使用hash值算法计算。 22 Hash string `json:"hash"` 23 24 // 资源内容的大小,单位:字节。 25 Fsize int64 `json:"fsize"` 26 27 // 资源的 MIME 类型。 28 MimeType string `json:"mimeType"` 29 30 /** 31 * 文件上传时设置的endUser 32 */ 33 EndUser string `json:"endUser"` 34 35 /** 36 * 资源的存储类型 37 * 0 表示标准存储 38 * 1 表示低频存储 39 * 2 表示归档存储 40 * 3 表示深度归档存储 41 * 4 表示归档存储直读 42 */ 43 Type int `json:"type"` 44 45 /** 46 * 文件的存储状态,即禁用状态和启用状态间的的互相转换,请参考:文件状态。 47 * 0 表示启用 48 * 1 表示禁用 49 */ 50 Status int `json:"status"` 51 52 /** 53 * 文件的 md5 值 54 */ 55 Md5 string `json:"md5"` 56 57 /** 58 * 文件的分片信息 59 */ 60 Parts []uint `json:"parts"` 61 } 62 63 // 接口可能返回空的记录 64 func (l *ListItem) IsEmpty() (empty bool) { 65 if l == nil { 66 return true 67 } 68 69 return l.Key == "" && l.Hash == "" && l.Fsize == 0 && l.PutTime == 0 70 } 71 72 func (l *ListItem) String() string { 73 str := "" 74 str += fmt.Sprintf("Hash: %s\n", l.Hash) 75 str += fmt.Sprintf("Fsize: %d\n", l.Fsize) 76 str += fmt.Sprintf("PutTime: %d\n", l.PutTime) 77 str += fmt.Sprintf("MimeType: %s\n", l.MimeType) 78 str += fmt.Sprintf("Type: %d\n", l.Type) 79 str += fmt.Sprintf("EndUser: %s\n", l.EndUser) 80 return str 81 } 82 83 type ListFilesRet struct { 84 Marker string `json:"marker"` 85 Items []ListItem `json:"items"` 86 CommonPrefixes []string `json:"commonPrefixes"` 87 } 88 89 // ListFiles 用来获取空间文件列表,可以根据需要指定文件的前缀 prefix,文件的目录 delimiter,循环列举的时候下次 90 // 列举的位置 marker,以及每次返回的文件的最大数量limit,其中limit最大为1000。 91 func (m *BucketManager) ListFiles(bucket, prefix, delimiter, marker string, 92 limit int, 93 ) (entries []ListItem, commonPrefixes []string, nextMarker string, hasNext bool, err error) { 94 ret, hNext, e := m.ListFilesWithContext(context.Background(), bucket, 95 ListInputOptionsPrefix(prefix), 96 ListInputOptionsDelimiter(delimiter), 97 ListInputOptionsMarker(marker), 98 ListInputOptionsLimit(limit)) 99 if e != nil { 100 return nil, nil, "", false, e 101 } 102 return ret.Items, ret.CommonPrefixes, ret.Marker, hNext, nil 103 } 104 105 type listInputOptions struct { 106 prefix string 107 delimiter string 108 marker string 109 limit int 110 needParts bool 111 } 112 113 type ListInputOption func(options *listInputOptions) 114 115 func ListInputOptionsPrefix(prefix string) ListInputOption { 116 return func(input *listInputOptions) { 117 input.prefix = prefix 118 } 119 } 120 121 func ListInputOptionsDelimiter(delimiter string) ListInputOption { 122 return func(input *listInputOptions) { 123 input.delimiter = delimiter 124 } 125 } 126 127 func ListInputOptionsMarker(marker string) ListInputOption { 128 return func(input *listInputOptions) { 129 input.marker = marker 130 } 131 } 132 133 func ListInputOptionsLimit(limit int) ListInputOption { 134 return func(input *listInputOptions) { 135 input.limit = limit 136 } 137 } 138 139 func ListInputOptionsNeedParts(needParts bool) ListInputOption { 140 return func(input *listInputOptions) { 141 input.needParts = needParts 142 } 143 } 144 145 // ListFilesWithContext 146 // 147 // @Description: 用来获取空间文件列表,可以根据需要指定文件的列举条件 148 // @receiver m BucketManager 149 // @param ctx context 150 // @param bucket 列举的 bucket 151 // @param options 列举的可选条件 152 // 列举条件-需要列举 Key 的前缀:ListInputOptionsPrefix(prefix) 153 // 列举条件-文件的目录分隔符:ListInputOptionsDelimiter(delimiter) 154 // 列举条件-下次列举的位置:ListInputOptionsMarker(marker) 155 // 列举条件-每次返回的文件的最大数量:ListInputOptionsLimit(limit) 范围:1~1000 156 // @return ret 列举的对象数据 157 // @return hasNext 是否还有数据未被列举 158 // @return err 列举时的错误信息 159 func (m *BucketManager) ListFilesWithContext(ctx context.Context, bucket string, options ...ListInputOption) (ret *ListFilesRet, hasNext bool, err error) { 160 if len(bucket) == 0 { 161 return nil, false, errors.New("bucket can't empty") 162 } 163 164 inputOptions := listInputOptions{} 165 for _, option := range options { 166 option(&inputOptions) 167 } 168 169 if inputOptions.limit <= 0 || inputOptions.limit > 1000 { 170 return nil, false, errors.New("invalid list limit, only allow [1, 1000]") 171 } 172 173 ctx = auth.WithCredentialsType(ctx, m.Mac, auth.TokenQiniu) 174 host, reqErr := m.RsfReqHost(bucket) 175 if reqErr != nil { 176 return nil, false, reqErr 177 } 178 179 ret = &ListFilesRet{} 180 reqURL := fmt.Sprintf("%s%s", host, uriListFiles(bucket, inputOptions.prefix, inputOptions.delimiter, inputOptions.marker, inputOptions.limit, inputOptions.needParts)) 181 err = m.Client.CredentialedCall(ctx, m.Mac, auth.TokenQiniu, ret, "POST", reqURL, nil) 182 if err != nil { 183 return nil, false, err 184 } 185 186 return ret, len(ret.Marker) > 0, nil 187 } 188 189 type listFilesRet2 struct { 190 Marker string `json:"marker"` 191 Item ListItem `json:"item"` 192 Dir string `json:"dir"` 193 } 194 195 // ListBucket 用来获取空间文件列表,可以根据需要指定文件的前缀 prefix,文件的目录 delimiter,流式返回每条数据。 196 // Deprecated 197 func (m *BucketManager) ListBucket(bucket, prefix, delimiter, marker string) (retCh chan listFilesRet2, err error) { 198 return m.ListBucketContext(context.Background(), bucket, prefix, delimiter, marker) 199 } 200 201 // ListBucketContext 用来获取空间文件列表,可以根据需要指定文件的前缀 prefix,文件的目录 delimiter,流式返回每条数据。 202 // 接受的context可以用来取消列举操作 203 // Deprecated 204 func (m *BucketManager) ListBucketContext(ctx context.Context, bucket, prefix, delimiter, marker string) (retCh chan listFilesRet2, err error) { 205 ret, _, lErr := m.ListFilesWithContext(ctx, bucket, 206 ListInputOptionsLimit(250), 207 ListInputOptionsPrefix(prefix), 208 ListInputOptionsDelimiter(delimiter), 209 ListInputOptionsMarker(marker)) 210 if lErr != nil { 211 return nil, lErr 212 } 213 214 count := len(ret.CommonPrefixes) + len(ret.Items) 215 retCh = make(chan listFilesRet2, count) 216 defer close(retCh) 217 218 if len(ret.CommonPrefixes) > 0 { 219 for _, commonPrefix := range ret.CommonPrefixes { 220 retCh <- listFilesRet2{ 221 Marker: ret.Marker, 222 Item: ListItem{}, 223 Dir: commonPrefix, 224 } 225 } 226 } 227 228 if len(ret.Items) > 0 { 229 for _, item := range ret.Items { 230 retCh <- listFilesRet2{ 231 Marker: ret.Marker, 232 Item: item, 233 Dir: "", 234 } 235 } 236 } 237 238 return retCh, err 239 } 240 241 func uriListFiles(bucket, prefix, delimiter, marker string, limit int, needParts bool) string { 242 query := make(url.Values) 243 query.Add("bucket", bucket) 244 if prefix != "" { 245 query.Add("prefix", prefix) 246 } 247 if delimiter != "" { 248 query.Add("delimiter", delimiter) 249 } 250 if marker != "" { 251 query.Add("marker", marker) 252 } 253 if limit > 0 { 254 query.Add("limit", strconv.FormatInt(int64(limit), 10)) 255 } 256 query.Add("needparts", strconv.FormatBool(needParts)) 257 return fmt.Sprintf("/list?%s", query.Encode()) 258 }