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  }