Browse Source
Added File model (still missing edit/remove), fixed uploading to space always failing, added /upload endpoint to rpdata-grapihql server
1.0
Added File model (still missing edit/remove), fixed uploading to space always failing, added /upload endpoint to rpdata-grapihql server
1.0
Gisle Aune
7 years ago
3 changed files with 185 additions and 1 deletions
@ -0,0 +1,138 @@ |
|||||
|
package file |
||||
|
|
||||
|
import ( |
||||
|
"context" |
||||
|
"crypto/rand" |
||||
|
"encoding/binary" |
||||
|
"io" |
||||
|
"strconv" |
||||
|
"time" |
||||
|
|
||||
|
"git.aiterp.net/rpdata/api/internal/store" |
||||
|
"github.com/globalsign/mgo" |
||||
|
"github.com/globalsign/mgo/bson" |
||||
|
) |
||||
|
|
||||
|
var fileCollection *mgo.Collection |
||||
|
|
||||
|
// A File is a record of a file stored in the Space.
|
||||
|
type File struct { |
||||
|
ID string `bson:"_id" json:"id"` |
||||
|
Time time.Time `bson:"time" json:"time"` |
||||
|
Public bool `bson:"public" json:"public"` |
||||
|
Name string `bson:"name" json:"name"` |
||||
|
MimeType string `bson:"mimeType" json:"mimeType"` |
||||
|
Size int64 `bson:"size" json:"size"` |
||||
|
Author string `bson:"author" json:"author"` |
||||
|
URL string `bson:"url,omitempty" json:"url,omitempty"` |
||||
|
} |
||||
|
|
||||
|
// Upload adds a file to the space.
|
||||
|
func Upload(ctx context.Context, name, mimeType, author string, size int64, input io.Reader) (File, error) { |
||||
|
if name == "" { |
||||
|
date := time.Now().UTC().Format("Jan 02 2006 15:04:05 MST") |
||||
|
name = "Unnamed file (" + date + ")" |
||||
|
} |
||||
|
|
||||
|
if mimeType == "" { |
||||
|
mimeType = "binary/octet-stream" |
||||
|
} |
||||
|
|
||||
|
id := makeFileID() |
||||
|
|
||||
|
path, err := store.UploadFile(ctx, "files", id, mimeType, input, size) |
||||
|
if err != nil { |
||||
|
return File{}, err |
||||
|
} |
||||
|
|
||||
|
file := File{ |
||||
|
ID: id, |
||||
|
Time: time.Now(), |
||||
|
Public: false, |
||||
|
Author: author, |
||||
|
Name: name, |
||||
|
MimeType: mimeType, |
||||
|
Size: size, |
||||
|
URL: store.URLFromPath(path), |
||||
|
} |
||||
|
|
||||
|
err = fileCollection.Insert(file) |
||||
|
if err != nil { |
||||
|
return File{}, err |
||||
|
} |
||||
|
|
||||
|
return file, nil |
||||
|
} |
||||
|
|
||||
|
// FindID finds a file by ID
|
||||
|
func FindID(id string) (File, error) { |
||||
|
file := File{} |
||||
|
|
||||
|
err := fileCollection.FindId(id).One(&file) |
||||
|
if err != nil { |
||||
|
return File{}, err |
||||
|
} |
||||
|
|
||||
|
return file, nil |
||||
|
} |
||||
|
|
||||
|
// ListFiles lists files according to the standard lookup. By default it's just the author's own files,
|
||||
|
// but if `public` is true it will alos include files made public by other authors. If `mimeTypes` contains
|
||||
|
// any, it will limit the results to that.
|
||||
|
func ListFiles(author string, public bool, mimeTypes []string) ([]File, error) { |
||||
|
query := bson.M{} |
||||
|
|
||||
|
if public { |
||||
|
query["$or"] = []bson.M{ |
||||
|
bson.M{"author": author}, |
||||
|
bson.M{"public": true}, |
||||
|
} |
||||
|
} else { |
||||
|
query["author"] = author |
||||
|
} |
||||
|
|
||||
|
if len(mimeTypes) > 0 { |
||||
|
query["mimeTypes"] = bson.M{"$in": mimeTypes} |
||||
|
} |
||||
|
|
||||
|
return listFiles(query) |
||||
|
} |
||||
|
|
||||
|
func listFiles(query interface{}) ([]File, error) { |
||||
|
list := make([]File, 0, 32) |
||||
|
|
||||
|
err := fileCollection.Find(query).All(&list) |
||||
|
if err != nil { |
||||
|
return nil, err |
||||
|
} |
||||
|
|
||||
|
return list, nil |
||||
|
} |
||||
|
|
||||
|
// makeFileID makes a random file ID that's 32 characters long
|
||||
|
func makeFileID() string { |
||||
|
result := "F" + strconv.FormatInt(time.Now().UnixNano(), 36) |
||||
|
offset := 0 |
||||
|
data := make([]byte, 32) |
||||
|
|
||||
|
rand.Read(data) |
||||
|
for len(result) < 32 { |
||||
|
result += strconv.FormatUint(binary.LittleEndian.Uint64(data[offset:]), 36) |
||||
|
offset += 8 |
||||
|
|
||||
|
if offset >= 32 { |
||||
|
rand.Read(data) |
||||
|
offset = 0 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result[:32] |
||||
|
} |
||||
|
|
||||
|
func init() { |
||||
|
store.HandleInit(func(db *mgo.Database) { |
||||
|
fileCollection = db.C("file.headers") |
||||
|
|
||||
|
fileCollection.EnsureIndexKey("author") |
||||
|
}) |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue