mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2024-11-26 22:20:18 +01:00
updated readme & go formatted code
This commit is contained in:
parent
16ad1833d2
commit
b8eaf23805
4 changed files with 92 additions and 91 deletions
|
@ -1,6 +1,8 @@
|
||||||
# transfer.sh
|
# transfer.sh
|
||||||
|
|
||||||
Easy and fast file sharing from the command-line. This code contains the server with everything you need to create your own instance. Transfer.sh currently runs on top of Amazon S3. Other storage types will be added shortly.
|
Easy and fast file sharing from the command-line. This code contains the server with everything you need to create your own instance.
|
||||||
|
|
||||||
|
Transfer.sh support currently the s3 (Amazon S3) provider and local file system (local).
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/dutchcoders/transfer.sh.svg?branch=master)](https://travis-ci.org/dutchcoders/transfer.sh)
|
[![Build Status](https://travis-ci.org/dutchcoders/transfer.sh.svg?branch=master)](https://travis-ci.org/dutchcoders/transfer.sh)
|
||||||
|
|
||||||
|
|
|
@ -38,19 +38,19 @@ import (
|
||||||
"github.com/golang/gddo/httputil/header"
|
"github.com/golang/gddo/httputil/header"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/kennygrant/sanitize"
|
"github.com/kennygrant/sanitize"
|
||||||
|
html_template "html/template"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"strconv"
|
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
html_template "html/template"
|
|
||||||
text_template "text/template"
|
text_template "text/template"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func healthHandler(w http.ResponseWriter, r *http.Request) {
|
func healthHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -101,7 +101,7 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
|
func notFoundHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
http.Error(w, http.StatusText(404), 404)
|
http.Error(w, http.StatusText(404), 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
func postHandler(w http.ResponseWriter, r *http.Request) {
|
func postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -169,7 +169,7 @@ func postHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
log.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
|
log.Printf("Uploading %s %s %d %s", token, filename, contentLength, contentType)
|
||||||
|
|
||||||
if err = storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
|
if err = storage.Put(token, filename, reader, contentType, uint64(contentLength)); err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
return
|
return
|
||||||
|
@ -275,7 +275,7 @@ func putHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
contentType = mime.TypeByExtension(filepath.Ext(vars["filename"]))
|
contentType = mime.TypeByExtension(filepath.Ext(vars["filename"]))
|
||||||
}
|
}
|
||||||
|
|
||||||
token := Encode(10000000+int64(rand.Intn(1000000000)))
|
token := Encode(10000000 + int64(rand.Intn(1000000000)))
|
||||||
|
|
||||||
log.Printf("Uploading %s %d %s", token, filename, contentLength, contentType)
|
log.Printf("Uploading %s %d %s", token, filename, contentLength, contentType)
|
||||||
|
|
||||||
|
@ -307,8 +307,8 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
zw := zip.NewWriter(w)
|
zw := zip.NewWriter(w)
|
||||||
|
|
||||||
for _, key := range strings.Split(files, ",") {
|
for _, key := range strings.Split(files, ",") {
|
||||||
token := sanitize.Path(strings.Split(key, "/")[0])
|
token := sanitize.Path(strings.Split(key, "/")[0])
|
||||||
filename := sanitize.Path(strings.Split(key, "/")[1])
|
filename := sanitize.Path(strings.Split(key, "/")[1])
|
||||||
|
|
||||||
reader, _, _, err := storage.Get(token, filename)
|
reader, _, _, err := storage.Get(token, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -322,7 +322,7 @@ func zipHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
header := &zip.FileHeader{
|
header := &zip.FileHeader{
|
||||||
Name: strings.Split(key, "/")[1],
|
Name: strings.Split(key, "/")[1],
|
||||||
|
@ -371,8 +371,8 @@ func tarGzHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
defer zw.Close()
|
defer zw.Close()
|
||||||
|
|
||||||
for _, key := range strings.Split(files, ",") {
|
for _, key := range strings.Split(files, ",") {
|
||||||
token := strings.Split(key, "/")[0]
|
token := strings.Split(key, "/")[0]
|
||||||
filename := strings.Split(key, "/")[1]
|
filename := strings.Split(key, "/")[1]
|
||||||
|
|
||||||
reader, _, contentLength, err := storage.Get(token, filename)
|
reader, _, contentLength, err := storage.Get(token, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -386,7 +386,7 @@ func tarGzHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
header := &tar.Header{
|
header := &tar.Header{
|
||||||
Name: strings.Split(key, "/")[1],
|
Name: strings.Split(key, "/")[1],
|
||||||
|
@ -423,8 +423,8 @@ func tarHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
defer zw.Close()
|
defer zw.Close()
|
||||||
|
|
||||||
for _, key := range strings.Split(files, ",") {
|
for _, key := range strings.Split(files, ",") {
|
||||||
token := strings.Split(key, "/")[0]
|
token := strings.Split(key, "/")[0]
|
||||||
filename := strings.Split(key, "/")[1]
|
filename := strings.Split(key, "/")[1]
|
||||||
|
|
||||||
reader, _, contentLength, err := storage.Get(token, filename)
|
reader, _, contentLength, err := storage.Get(token, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -438,7 +438,7 @@ func tarHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
header := &tar.Header{
|
header := &tar.Header{
|
||||||
Name: strings.Split(key, "/")[1],
|
Name: strings.Split(key, "/")[1],
|
||||||
|
@ -466,7 +466,7 @@ func getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
token := vars["token"]
|
token := vars["token"]
|
||||||
filename := vars["filename"]
|
filename := vars["filename"]
|
||||||
|
|
||||||
reader, contentType, contentLength, err := storage.Get(token, filename)
|
reader, contentType, contentLength, err := storage.Get(token, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() == "The specified key does not exist." {
|
if err.Error() == "The specified key does not exist." {
|
||||||
http.Error(w, "File not found", 404)
|
http.Error(w, "File not found", 404)
|
||||||
|
@ -478,10 +478,10 @@ func getHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
|
||||||
w.Header().Set("Content-Type", contentType)
|
w.Header().Set("Content-Type", contentType)
|
||||||
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
|
w.Header().Set("Content-Length", strconv.FormatUint(contentLength, 10))
|
||||||
|
|
||||||
mediaType, _, _ := mime.ParseMediaType(contentType)
|
mediaType, _, _ := mime.ParseMediaType(contentType)
|
||||||
|
|
||||||
|
|
|
@ -131,23 +131,23 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Temp = *temp
|
config.Temp = *temp
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch *provider {
|
var err error
|
||||||
case "s3":
|
|
||||||
storage, err = NewS3Storage()
|
|
||||||
case "local":
|
|
||||||
if *basedir == "" {
|
|
||||||
log.Panic("basedir not set")
|
|
||||||
}
|
|
||||||
|
|
||||||
storage, err = NewLocalStorage(*basedir)
|
switch *provider {
|
||||||
}
|
case "s3":
|
||||||
|
storage, err = NewS3Storage()
|
||||||
|
case "local":
|
||||||
|
if *basedir == "" {
|
||||||
|
log.Panic("basedir not set")
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
storage, err = NewLocalStorage(*basedir)
|
||||||
log.Panic("Error while creating storage.")
|
}
|
||||||
}
|
|
||||||
|
if err != nil {
|
||||||
|
log.Panic("Error while creating storage.")
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("Transfer.sh server started. :%v using temp folder: %s", *port, config.Temp)
|
log.Printf("Transfer.sh server started. :%v using temp folder: %s", *port, config.Temp)
|
||||||
log.Printf("---------------------------")
|
log.Printf("---------------------------")
|
||||||
|
|
|
@ -1,100 +1,99 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"fmt"
|
||||||
"github.com/goamz/goamz/s3"
|
"github.com/goamz/goamz/s3"
|
||||||
"strconv"
|
"io"
|
||||||
"fmt"
|
"os"
|
||||||
"os"
|
"path/filepath"
|
||||||
"path/filepath"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Storage interface {
|
type Storage interface {
|
||||||
Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error)
|
Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error)
|
||||||
Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error
|
Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type LocalStorage struct {
|
type LocalStorage struct {
|
||||||
Storage
|
Storage
|
||||||
basedir string
|
basedir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLocalStorage(basedir string) (*LocalStorage, error) {
|
func NewLocalStorage(basedir string) (*LocalStorage, error) {
|
||||||
return &LocalStorage {basedir: basedir}, nil
|
return &LocalStorage{basedir: basedir}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
||||||
|
path := filepath.Join(s.basedir, token, filename)
|
||||||
|
|
||||||
func (s *LocalStorage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
// content type , content length
|
||||||
path := filepath.Join(s.basedir, token, filename)
|
if reader, err = os.Open(path); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// content type , content length
|
var fi os.FileInfo
|
||||||
if reader, err = os.Open(path); err != nil {
|
if fi, err = os.Lstat(path); err != nil {
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var fi os.FileInfo
|
contentLength = uint64(fi.Size())
|
||||||
if fi, err = os.Lstat(path); err != nil {
|
|
||||||
}
|
|
||||||
|
|
||||||
contentLength = uint64(fi.Size())
|
contentType = ""
|
||||||
|
|
||||||
contentType = ""
|
return
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LocalStorage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
func (s *LocalStorage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
||||||
var f io.WriteCloser
|
var f io.WriteCloser
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
path := filepath.Join(s.basedir, token)
|
path := filepath.Join(s.basedir, token)
|
||||||
|
|
||||||
if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
|
if err = os.Mkdir(path, 0700); err != nil && !os.IsExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
|
if f, err = os.OpenFile(filepath.Join(path, filename), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600); err != nil {
|
||||||
fmt.Printf("%s", err)
|
fmt.Printf("%s", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
if _, err = io.Copy(f, reader); err != nil {
|
if _, err = io.Copy(f, reader); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type S3Storage struct {
|
type S3Storage struct {
|
||||||
Storage
|
Storage
|
||||||
bucket *s3.Bucket
|
bucket *s3.Bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewS3Storage() (*S3Storage, error) {
|
func NewS3Storage() (*S3Storage, error) {
|
||||||
bucket, err := getBucket()
|
bucket, err := getBucket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &S3Storage {bucket: bucket}, nil
|
return &S3Storage{bucket: bucket}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
func (s *S3Storage) Get(token string, filename string) (reader io.ReadCloser, contentType string, contentLength uint64, err error) {
|
||||||
key := fmt.Sprintf("%s/%s", token, filename)
|
key := fmt.Sprintf("%s/%s", token, filename)
|
||||||
|
|
||||||
// content type , content length
|
// content type , content length
|
||||||
response, err := s.bucket.GetResponse(key)
|
response, err := s.bucket.GetResponse(key)
|
||||||
contentType = ""
|
contentType = ""
|
||||||
contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
|
contentLength, err = strconv.ParseUint(response.Header.Get("Content-Length"), 10, 0)
|
||||||
|
|
||||||
reader = response.Body
|
reader = response.Body
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *S3Storage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
func (s *S3Storage) Put(token string, filename string, reader io.Reader, contentType string, contentLength uint64) error {
|
||||||
key := fmt.Sprintf("%s/%s", token, filename)
|
key := fmt.Sprintf("%s/%s", token, filename)
|
||||||
err := s.bucket.PutReader(key, reader, int64(contentLength), contentType, s3.Private, s3.Options{})
|
err := s.bucket.PutReader(key, reader, int64(contentLength), contentType, s3.Private, s3.Options{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue