github.com/qiniu/go-sdk/v7@v7.27.0/storage/recorder.go (about)

     1  package storage
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/sha1"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  	"strconv"
    10  	"strings"
    11  	"time"
    12  )
    13  
    14  type Recorder interface {
    15  	// 新建或更新文件分片上传的进度
    16  	Set(key string, data []byte) error
    17  
    18  	// 获取文件分片上传的进度信息
    19  	Get(key string) ([]byte, error)
    20  
    21  	// 删除文件分片上传的进度文件
    22  	Delete(key string) error
    23  
    24  	// 根据给定的文件信息生成持久化纪录的 key
    25  	GenerateRecorderKey(keyInfos []string, sourceFileInfo os.FileInfo) string
    26  }
    27  
    28  type FileRecorder struct {
    29  	directoryPath string
    30  }
    31  
    32  func NewFileRecorder(directoryPath string) (fileRecorder *FileRecorder, err error) {
    33  	err = os.MkdirAll(directoryPath, 0700)
    34  	if err != nil {
    35  		return
    36  	}
    37  	fileRecorder = &FileRecorder{directoryPath: directoryPath}
    38  	return
    39  }
    40  
    41  func (fileRecorder *FileRecorder) Set(key string, data []byte) error {
    42  	path := filepath.Join(fileRecorder.directoryPath, key)
    43  	file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    44  	if err != nil {
    45  		return err
    46  	}
    47  	defer file.Close()
    48  	_, err = io.Copy(file, bytes.NewReader(data))
    49  	return err
    50  }
    51  
    52  func (fileRecorder *FileRecorder) Get(key string) ([]byte, error) {
    53  	path := filepath.Join(fileRecorder.directoryPath, key)
    54  	file, err := os.Open(path)
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	defer file.Close()
    59  
    60  	fileInfo, err := file.Stat()
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  	if isRecorderFileOutOfDate(fileInfo) {
    65  		err = fileRecorder.Delete(key)
    66  		return nil, err
    67  	}
    68  
    69  	buffer := new(bytes.Buffer)
    70  	_, err = io.Copy(buffer, file)
    71  	return buffer.Bytes(), err
    72  }
    73  
    74  func (fileRecorder *FileRecorder) Delete(key string) error {
    75  	path := filepath.Join(fileRecorder.directoryPath, key)
    76  	return os.Remove(path)
    77  }
    78  
    79  func (fileRecorder *FileRecorder) GenerateRecorderKey(keyInfos []string, sourceFileInfo os.FileInfo) string {
    80  	const delimiter = "*:|>?^ \b"
    81  	buffer := new(bytes.Buffer)
    82  	for _, keyInfo := range keyInfos {
    83  		buffer.WriteString(keyInfo)
    84  		buffer.WriteString(delimiter)
    85  	}
    86  	buffer.WriteString(sourceFileInfo.ModTime().String())
    87  	return hashRecorderKey(buffer.Bytes())
    88  }
    89  
    90  func isRecorderFileOutOfDate(fileInfo os.FileInfo) bool {
    91  	return fileInfo.ModTime().Add(24 * 5 * time.Hour).Before(time.Now())
    92  }
    93  
    94  func hashRecorderKey(base []byte) string {
    95  	sha1edBase := sha1.Sum(base)
    96  
    97  	var stringBuilder strings.Builder
    98  	for i := 0; i < len(sha1edBase); i++ {
    99  		b := (int64(sha1edBase[i]) & 0xff) + 0x100
   100  		stringBuilder.WriteString(strconv.FormatInt(b, 16)[1:])
   101  	}
   102  	return stringBuilder.String()
   103  }