File uploads
This commit is contained in:
parent
8a3970645f
commit
86cedf9531
13
file.go
13
file.go
@ -46,12 +46,21 @@ func (session Session) AddFile(file *File) (err error) { // {{{
|
|||||||
fmt.Printf("%#v\n", file)
|
fmt.Printf("%#v\n", file)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func (session Session) Files(nodeID int) (files []File, err error) { // {{{
|
func (session Session) Files(nodeID, fileID int) (files []File, err error) { // {{{
|
||||||
var rows *sqlx.Rows
|
var rows *sqlx.Rows
|
||||||
rows, err = db.Queryx(
|
rows, err = db.Queryx(
|
||||||
`SELECT * FROM file WHERE user_id = $1 AND node_id = $2`,
|
`SELECT *
|
||||||
|
FROM file
|
||||||
|
WHERE
|
||||||
|
user_id = $1 AND
|
||||||
|
node_id = $2 AND
|
||||||
|
CASE $3::int
|
||||||
|
WHEN 0 THEN true
|
||||||
|
ELSE id = $3
|
||||||
|
END`,
|
||||||
session.UserID,
|
session.UserID,
|
||||||
nodeID,
|
nodeID,
|
||||||
|
fileID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
73
main.go
73
main.go
@ -20,7 +20,7 @@ import (
|
|||||||
_ "embed"
|
_ "embed"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "v0.1.2";
|
const VERSION = "v0.1.4";
|
||||||
const LISTEN_HOST = "0.0.0.0";
|
const LISTEN_HOST = "0.0.0.0";
|
||||||
const DB_SCHEMA = 5
|
const DB_SCHEMA = 5
|
||||||
|
|
||||||
@ -31,7 +31,6 @@ var (
|
|||||||
config Config
|
config Config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func init() {// {{{
|
func init() {// {{{
|
||||||
flag.IntVar(
|
flag.IntVar(
|
||||||
&flagPort,
|
&flagPort,
|
||||||
@ -76,6 +75,7 @@ func main() {// {{{
|
|||||||
http.HandleFunc("/node/rename", nodeRename)
|
http.HandleFunc("/node/rename", nodeRename)
|
||||||
http.HandleFunc("/node/delete", nodeDelete)
|
http.HandleFunc("/node/delete", nodeDelete)
|
||||||
http.HandleFunc("/node/upload", nodeUpload)
|
http.HandleFunc("/node/upload", nodeUpload)
|
||||||
|
http.HandleFunc("/node/download", nodeDownload)
|
||||||
http.HandleFunc("/ws", websocketHandler)
|
http.HandleFunc("/ws", websocketHandler)
|
||||||
http.HandleFunc("/", staticHandler)
|
http.HandleFunc("/", staticHandler)
|
||||||
|
|
||||||
@ -443,6 +443,73 @@ func nodeUpload(w http.ResponseWriter, r *http.Request) {// {{{
|
|||||||
"File": nodeFile,
|
"File": nodeFile,
|
||||||
})
|
})
|
||||||
}// }}}
|
}// }}}
|
||||||
|
func nodeDownload(w http.ResponseWriter, r *http.Request) {// {{{
|
||||||
|
log.Println("/node/download")
|
||||||
|
var err error
|
||||||
|
var session Session
|
||||||
|
var files []File
|
||||||
|
|
||||||
|
if session, _, err = ValidateSession(r, true); err != nil {
|
||||||
|
responseError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req := struct {
|
||||||
|
NodeID int
|
||||||
|
FileID int
|
||||||
|
}{}
|
||||||
|
if err = parseRequest(r, &req); err != nil {
|
||||||
|
responseError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
files, err = session.Files(req.NodeID, req.FileID)
|
||||||
|
if err != nil {
|
||||||
|
responseError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(files) != 1 {
|
||||||
|
responseError(w, fmt.Errorf("File not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var file *os.File
|
||||||
|
fname := filepath.Join(
|
||||||
|
config.Application.Directories.Upload,
|
||||||
|
files[0].MD5[0:1],
|
||||||
|
files[0].MD5[1:2],
|
||||||
|
files[0].MD5[2:3],
|
||||||
|
files[0].MD5,
|
||||||
|
)
|
||||||
|
file, err = os.Open(fname)
|
||||||
|
if err != nil {
|
||||||
|
responseError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var finfo os.FileInfo
|
||||||
|
finfo, err = file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
responseError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
read := 1
|
||||||
|
var buf []byte
|
||||||
|
for read > 0 {
|
||||||
|
buf = make([]byte, 65536)
|
||||||
|
read, err = file.Read(buf)
|
||||||
|
if read > 0 {
|
||||||
|
w.Write(buf[0:read])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Add("Content-Type", files[0].MIME)
|
||||||
|
w.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, files[0].Filename))
|
||||||
|
w.Header().Add("Content-Length", strconv.Itoa(int(finfo.Size())))
|
||||||
|
|
||||||
|
}// }}}
|
||||||
func nodeFiles(w http.ResponseWriter, r *http.Request) {// {{{
|
func nodeFiles(w http.ResponseWriter, r *http.Request) {// {{{
|
||||||
var err error
|
var err error
|
||||||
var session Session
|
var session Session
|
||||||
@ -461,7 +528,7 @@ func nodeFiles(w http.ResponseWriter, r *http.Request) {// {{{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
files, err = session.Files(req.NodeID)
|
files, err = session.Files(req.NodeID, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
responseError(w, err)
|
responseError(w, err)
|
||||||
return
|
return
|
||||||
|
2
node.go
2
node.go
@ -204,7 +204,7 @@ func (session Session) Node(nodeID int) (node Node, err error) {// {{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
node.Crumbs, err = session.NodeCrumbs(node.ID)
|
node.Crumbs, err = session.NodeCrumbs(node.ID)
|
||||||
node.Files, err = session.Files(node.ID)
|
node.Files, err = session.Files(node.ID, 0)
|
||||||
|
|
||||||
return
|
return
|
||||||
}// }}}
|
}// }}}
|
||||||
|
@ -204,7 +204,7 @@ header .menu {
|
|||||||
#file-section {
|
#file-section {
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
margin-top: 32px;
|
margin-top: 16px;
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
}
|
}
|
||||||
@ -224,6 +224,10 @@ header .menu {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#file-section .files .filename:hover {
|
||||||
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
#file-section .files .size {
|
#file-section .files .size {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@ -232,13 +236,17 @@ header .menu {
|
|||||||
.tree {
|
.tree {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
@media only screen and (max-width: 100ex) {
|
@media only screen and (max-width: 932px) {
|
||||||
.node-content {
|
.node-content {
|
||||||
width: 100%;
|
width: calc(100% - 32px);
|
||||||
|
margin-left: 16px;
|
||||||
|
padding: 16px;
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
}
|
}
|
||||||
#file-section {
|
#file-section {
|
||||||
width: 100%;
|
width: calc(100% - 32px);
|
||||||
|
padding: 16px;
|
||||||
|
margin-left: 16px;
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ class NodeFiles extends Component {
|
|||||||
})
|
})
|
||||||
.map(file=>
|
.map(file=>
|
||||||
html`
|
html`
|
||||||
<div class="filename">${file.Filename}</div>
|
<div class="filename" onclick=${()=>node.download(file.ID)}>${file.Filename}</div>
|
||||||
<div class="size">${this.formatSize(file.Size)}</div>
|
<div class="size">${this.formatSize(file.Size)}</div>
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
@ -308,6 +308,37 @@ class Node {
|
|||||||
.then(callback)
|
.then(callback)
|
||||||
.catch(this.app.responseError)
|
.catch(this.app.responseError)
|
||||||
}//}}}
|
}//}}}
|
||||||
|
download(fileID) {//{{{
|
||||||
|
let headers = {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.app.session.UUID !== '')
|
||||||
|
headers['X-Session-Id'] = this.app.session.UUID
|
||||||
|
|
||||||
|
let fname = ""
|
||||||
|
fetch("/node/download", {
|
||||||
|
method: 'POST',
|
||||||
|
headers,
|
||||||
|
body: JSON.stringify({
|
||||||
|
NodeID: this.ID,
|
||||||
|
FileID: fileID,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then(response=>{
|
||||||
|
console.log(...response.headers);
|
||||||
|
return response.blob()
|
||||||
|
})
|
||||||
|
.then(blob=>{
|
||||||
|
let url = window.URL.createObjectURL(blob)
|
||||||
|
let a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = "filename.xlsx";
|
||||||
|
document.body.appendChild(a); // we need to append the element to the dom -> otherwise it will not work in firefox
|
||||||
|
a.click();
|
||||||
|
a.remove(); //afterwards we remove the element again
|
||||||
|
})
|
||||||
|
}//}}}
|
||||||
children(callback) {//{{{
|
children(callback) {//{{{
|
||||||
this.app.request('/node/tree', { StartNodeID: this.ID })
|
this.app.request('/node/tree', { StartNodeID: this.ID })
|
||||||
.then(res=>{
|
.then(res=>{
|
||||||
|
@ -240,7 +240,7 @@ header {
|
|||||||
#file-section {
|
#file-section {
|
||||||
justify-self: center;
|
justify-self: center;
|
||||||
width: 900px;
|
width: 900px;
|
||||||
margin-top: 32px;
|
margin-top: 16px;
|
||||||
padding: 32px;
|
padding: 32px;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
|
|
||||||
@ -261,6 +261,11 @@ header {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.size {
|
.size {
|
||||||
@ -274,14 +279,18 @@ header {
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 100ex) {
|
@media only screen and (max-width: 932px) {
|
||||||
.node-content {
|
.node-content {
|
||||||
width: 100%;
|
width: calc(100% - 32px);
|
||||||
|
margin-left: 16px;
|
||||||
|
padding: 16px;
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
}
|
}
|
||||||
|
|
||||||
#file-section {
|
#file-section {
|
||||||
width: 100%;
|
width: calc(100% - 32px);
|
||||||
|
padding: 16px;
|
||||||
|
margin-left: 16px;
|
||||||
justify-self: start;
|
justify-self: start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user