Merge pull request #13 from gmemstr/simplify-filetransfer

This commit is contained in:
Gabriel Simmer 2021-05-23 15:44:02 +01:00 committed by GitHub
commit 40724cbdef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 54 additions and 62 deletions

View file

@ -7,7 +7,9 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"mime"
"net/http" "net/http"
"path/filepath"
"strings" "strings"
) )
@ -138,11 +140,7 @@ func (bp *BackblazeProvider) GetDirectory(path string) Directory {
return finalDir return finalDir
} }
func (bp *BackblazeProvider) FilePath(path string) string { func (bp *BackblazeProvider) SendFile(path string, w io.Writer) (stream io.Reader, contenttype string, err error) {
return ""
}
func (bp *BackblazeProvider) RemoteFile(path string, w io.Writer) {
client := &http.Client{} client := &http.Client{}
// Get bucket name >:( // Get bucket name >:(
bucketIdPayload := fmt.Sprintf(`{"accountId": "%s", "bucketId": "%s"}`, bp.Name, bp.Bucket) bucketIdPayload := fmt.Sprintf(`{"accountId": "%s", "bucketId": "%s"}`, bp.Name, bp.Bucket)
@ -150,20 +148,17 @@ func (bp *BackblazeProvider) RemoteFile(path string, w io.Writer) {
req, err := http.NewRequest("POST", bp.Location + "/b2api/v2/b2_list_buckets", req, err := http.NewRequest("POST", bp.Location + "/b2api/v2/b2_list_buckets",
bytes.NewBuffer([]byte(bucketIdPayload))) bytes.NewBuffer([]byte(bucketIdPayload)))
if err != nil { if err != nil {
fmt.Println(err.Error()) return nil, contenttype, err
return
} }
req.Header.Add("Authorization", bp.Authentication) req.Header.Add("Authorization", bp.Authentication)
res, err := client.Do(req) res, err := client.Do(req)
if err != nil { if err != nil {
fmt.Println(err.Error()) return nil, contenttype, err
return
} }
bucketData, err := ioutil.ReadAll(res.Body) bucketData, err := ioutil.ReadAll(res.Body)
if err != nil { if err != nil {
fmt.Println(err.Error()) return nil, contenttype, err
return
} }
var data BackblazeBucketInfoPayload var data BackblazeBucketInfoPayload
@ -175,22 +170,23 @@ func (bp *BackblazeProvider) RemoteFile(path string, w io.Writer) {
url, url,
bytes.NewBuffer([]byte(""))) bytes.NewBuffer([]byte("")))
if err != nil { if err != nil {
fmt.Println(err.Error()) return nil, contenttype, err
return
} }
req.Header.Add("Authorization", bp.Authentication) req.Header.Add("Authorization", bp.Authentication)
file, err := client.Do(req) file, err := client.Do(req)
if err != nil { if err != nil {
fmt.Println(err.Error()) return nil, contenttype, err
return
} }
_, err = io.Copy(w, file.Body) contenttype = mime.TypeByExtension(filepath.Ext(path))
if err != nil { if contenttype == "" {
fmt.Println(err.Error()) var buf [512]byte
return n, _ := io.ReadFull(file.Body, buf[:])
contenttype = http.DetectContentType(buf[:n])
} }
return file.Body, contenttype, err
} }
func (bp *BackblazeProvider) SaveFile(file io.Reader, filename string, path string) bool { func (bp *BackblazeProvider) SaveFile(file io.Reader, filename string, path string) bool {

View file

@ -4,7 +4,10 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"mime"
"net/http"
"os" "os"
"path/filepath"
"strings" "strings"
) )
@ -42,13 +45,22 @@ func (dp *DiskProvider) GetDirectory(path string) Directory {
} }
} }
func (dp *DiskProvider) FilePath(path string) string { func (dp *DiskProvider) SendFile(path string, writer io.Writer) (stream io.Reader, contenttype string, err error) {
rp := strings.Join([]string{dp.Location,path}, "/") rp := strings.Join([]string{dp.Location,path}, "/")
return rp f, err := os.Open(rp)
} if err != nil {
return stream, contenttype, err
}
func (dp *DiskProvider) RemoteFile(path string, writer io.Writer) { contenttype = mime.TypeByExtension(filepath.Ext(rp))
return
if contenttype == "" {
var buf [512]byte
n, _ := io.ReadFull(f, buf[:])
contenttype = http.DetectContentType(buf[:n])
}
return f, contenttype, nil
} }
func (dp *DiskProvider) SaveFile(file io.Reader, filename string, path string) bool { func (dp *DiskProvider) SaveFile(file io.Reader, filename string, path string) bool {

View file

@ -38,8 +38,7 @@ type FileInfo struct {
type FileProviderInterface interface { type FileProviderInterface interface {
Setup(args map[string]string) (ok bool) Setup(args map[string]string) (ok bool)
GetDirectory(path string) (directory Directory) GetDirectory(path string) (directory Directory)
FilePath(path string) (realpath string) SendFile(path string, writer io.Writer) (stream io.Reader, contenttype string, err error)
RemoteFile(path string, writer io.Writer)
SaveFile(file io.Reader, filename string, path string) (ok bool) SaveFile(file io.Reader, filename string, path string) (ok bool)
ObjectInfo(path string) (exists bool, isDir bool, location string) ObjectInfo(path string) (exists bool, isDir bool, location string)
CreateDirectory(path string) (ok bool) CreateDirectory(path string) (ok bool)
@ -58,13 +57,8 @@ func (f FileProvider) GetDirectory(path string) Directory {
return Directory{} return Directory{}
} }
// FilePath returns the path to the file, whether it be a URL or local file path.
func (f FileProvider) FilePath(path string) string {
return ""
}
// RemoteFile will bypass http.ServeContent() and instead write directly to the response. // RemoteFile will bypass http.ServeContent() and instead write directly to the response.
func (f FileProvider) RemoteFile(path string, writer io.Writer) { func (f FileProvider) SendFile(path string, writer io.Writer) (stream io.Reader, contenttype string, err error) {
return return
} }

View file

@ -24,10 +24,6 @@ func TestFileProvider(t *testing.T) {
t.Errorf("Default FileProvider GetDirectory() files returned %v, expected none.", getdirectory.Files) t.Errorf("Default FileProvider GetDirectory() files returned %v, expected none.", getdirectory.Files)
} }
filepath := fp.FilePath(""); if filepath != "" {
t.Errorf("Default FileProvider FilePath() %v, expected nothing.", filepath)
}
savefile := fp.SaveFile(nil, "", ""); if savefile != false { savefile := fp.SaveFile(nil, "", ""); if savefile != false {
t.Errorf("Default FileProvider SaveFile() attempted to save a file.") t.Errorf("Default FileProvider SaveFile() attempted to save a file.")
} }
@ -87,10 +83,6 @@ func TestDiskProvider(t *testing.T) {
t.Errorf("DiskProvider GetDirectory() files returned %v, expected 1.", getdirectory.Files) t.Errorf("DiskProvider GetDirectory() files returned %v, expected 1.", getdirectory.Files)
} }
filepath := dp.FilePath("testing.txt"); if filepath != DISK_TESTING_GROUNDS + "/testing.txt"{
t.Errorf("DiskProvider FilePath() returned %v, expected path.", filepath)
}
testfile := bytes.NewReader([]byte("second test file!")) testfile := bytes.NewReader([]byte("second test file!"))
savefile := dp.SaveFile(testfile, "second_test.txt", ""); if savefile != true { savefile := dp.SaveFile(testfile, "second_test.txt", ""); if savefile != true {
t.Errorf("DiskProvider SaveFile() could not save a file.") t.Errorf("DiskProvider SaveFile() could not save a file.")

View file

@ -3,14 +3,14 @@ package router
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/gmemstr/nas/files" "io"
"github.com/gorilla/mux"
"net/http" "net/http"
"net/url" "net/url"
"os"
"sort" "sort"
"strings" "strings"
"time"
"github.com/gmemstr/nas/files"
"github.com/gorilla/mux"
) )
func handleProvider() handler { func handleProvider() handler {
@ -29,7 +29,7 @@ func handleProvider() handler {
StatusCode: http.StatusInternalServerError, StatusCode: http.StatusInternalServerError,
} }
} }
ok, isDir, location := provider.ObjectInfo(filename) ok, isDir, _ := provider.ObjectInfo(filename)
if !ok { if !ok {
return &httpError{ return &httpError{
Message: fmt.Sprintf("error locating file %s\n", filename), Message: fmt.Sprintf("error locating file %s\n", filename),
@ -49,27 +49,25 @@ func handleProvider() handler {
} }
w.Write(data) w.Write(data)
return nil return nil
} } else {
stream, contenttype, err := provider.SendFile(filename, w)
// If the file is local, attempt to use http.ServeContent for correct headers. if err != nil {
if location == files.FileIsLocal { return &httpError{
rp := provider.FilePath(filename) Message: fmt.Sprintf("error finding file %s\n", vars["file"]),
if rp != "" { StatusCode: http.StatusNotFound,
f, err := os.Open(rp) }
if err != nil { }
return &httpError{ w.Header().Set("Content-Type", contenttype)
Message: fmt.Sprintf("error opening file %s\n", rp), _, err = io.Copy(w, stream)
StatusCode: http.StatusInternalServerError, if err != nil {
} return &httpError{
Message: fmt.Sprintf("unable to write %s\n", vars["file"]),
StatusCode: http.StatusBadGateway,
} }
http.ServeContent(w, r, filename, time.Time{}, f)
} }
} }
// If the file is remote, then delegate the writing to the response to the provider.
// This isn't a great workaround, but avoids caching the whole file in mem or on disk.
if location == files.FileIsRemote {
provider.RemoteFile(filename, w)
}
return nil return nil
} }