Implement GetFileChunks
This commit is contained in:
parent
815964e4a8
commit
771703a40c
|
@ -4,8 +4,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DataStore struct {
|
type DataStore struct {
|
||||||
|
@ -53,6 +56,42 @@ func (s *DataStore) WriteFileChunk(id string, start int64, end int64, src io.Rea
|
||||||
return s.appendFileLog(id, fmt.Sprintf("%d,%d", start, end))
|
return s.appendFileLog(id, fmt.Sprintf("%d,%d", start, end))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DataStore) GetFileChunks(id string) (chunkSet, error) {
|
||||||
|
// @TODO stream the file / limit log file size?
|
||||||
|
data, err := ioutil.ReadFile(s.logPath(id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
lines := strings.Split(string(data), "\n")
|
||||||
|
|
||||||
|
chunks := make(chunkSet, 0, len(lines)-1)
|
||||||
|
for i, line := range lines {
|
||||||
|
// last line is always empty, skip it
|
||||||
|
if lastLine := i+1 == len(lines); lastLine {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(line, ",")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return nil, errors.New("getReceivedChunks: corrupt log line: " + line)
|
||||||
|
}
|
||||||
|
|
||||||
|
start, err := strconv.ParseInt(parts[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("getReceivedChunks: invalid start: " + parts[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
end, err := strconv.ParseInt(parts[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("getReceivedChunks: invalid end: " + parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks.Add(chunk{Start: start, End: end})
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunks, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DataStore) appendFileLog(id string, entry string) error {
|
func (s *DataStore) appendFileLog(id string, entry string) error {
|
||||||
logPath := s.logPath(id)
|
logPath := s.logPath(id)
|
||||||
logFile, err := os.OpenFile(logPath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666)
|
logFile, err := os.OpenFile(logPath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
|
|
|
@ -143,21 +143,21 @@ func putFile(w http.ResponseWriter, r *http.Request, fileId string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFileRangeHeader(w http.ResponseWriter, fileId string) {
|
func setFileRangeHeader(w http.ResponseWriter, fileId string) {
|
||||||
chunks, err := getReceivedChunks(fileId)
|
chunks, err := dataStore.GetFileChunks(fileId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
reply(w, http.StatusInternalServerError, err.Error())
|
reply(w, http.StatusInternalServerError, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
received := ""
|
rangeHeader := ""
|
||||||
for i, chunk := range chunks {
|
for i, chunk := range chunks {
|
||||||
received += fmt.Sprintf("%d-%d", chunk.Start, chunk.End)
|
rangeHeader += fmt.Sprintf("%d-%d", chunk.Start, chunk.End)
|
||||||
if i+1 < len(chunks) {
|
if i+1 < len(chunks) {
|
||||||
received += ","
|
rangeHeader += ","
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if received != "" {
|
if rangeHeader != "" {
|
||||||
w.Header().Set("Range", "bytes="+received)
|
w.Header().Set("Range", "bytes="+rangeHeader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue