Skip to content
This repository has been archived by the owner on Dec 22, 2023. It is now read-only.

Commit

Permalink
Support getting asset with byte range in s3 asset store
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Lei committed Aug 10, 2018
1 parent 4889a9c commit 124191a
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions pkg/server/asset/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ package asset

import (
"errors"
"fmt"
"io"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -80,6 +82,39 @@ func (s *s3Store) GetFileReader(name string) (io.ReadCloser, error) {
return objOutput.Body, err
}

func (s *s3Store) GetRangedFileReader(
name string,
fileRange FileRange,
) (*FileRangedGetResult, error) {
key := aws.String(name)
rangeHeader := fmt.Sprintf("bytes=%d-%d", fileRange.From, fileRange.To)
input := &s3.GetObjectInput{
Bucket: s.bucket,
Key: key,
Range: &rangeHeader,
}

output, err := s.svc.GetObject(input)
if err != nil {
return nil, err
}

if output.ContentRange == nil {
return nil, errors.New("missing content ranges header")
}

acceptedRange, totalSize, err := parseContentRange(*output.ContentRange)
if err != nil {
return nil, err
}

return &FileRangedGetResult{
ReadCloser: output.Body,
AcceptedRange: acceptedRange,
TotalSize: totalSize,
}, nil
}

// PutFileReader uploads a file to s3 with content from io.Reader
func (s *s3Store) PutFileReader(
name string,
Expand Down Expand Up @@ -146,3 +181,42 @@ func (s *s3Store) ParseSignature(
"Asset signature parsing for s3-based asset store is not available",
)
}

// parseContentRange parses the content range string
// in the format of something like `bytes 123-567/1024`
//
func parseContentRange(contentRangeString string) (FileRange, int64, error) {
splits := strings.SplitN(contentRangeString, " ", 2)
if len(splits) != 2 {
return FileRange{}, 0, errors.New("content range is malformed")
}

if strings.ToLower(splits[0]) != "bytes" {
return FileRange{}, 0, errors.New(
"only support content range in unit of bytes",
)
}

compSplits := strings.SplitN(splits[1], "/", 2)
if len(compSplits) != 2 {
return FileRange{}, 0, errors.New("content range is malformed")
}

rangeSplits := strings.SplitN(compSplits[0], "-", 2)
if len(rangeSplits) != 2 {
return FileRange{}, 0, errors.New("content range is malformed")
}

rangeFrom, err1 := strconv.ParseInt(rangeSplits[0], 10, 64)
rangeTo, err2 := strconv.ParseInt(rangeSplits[1], 10, 64)
totalSize, err3 := strconv.ParseInt(compSplits[1], 10, 64)

if err1 != nil || err2 != nil || err3 != nil {
return FileRange{}, 0, errors.New("content range is malformed")
}

return FileRange{
From: rangeFrom,
To: rangeTo,
}, totalSize, nil
}

0 comments on commit 124191a

Please sign in to comment.