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)
|
||||
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
|
||||
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,
|
||||
nodeID,
|
||||
fileID,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
|
73
main.go
73
main.go
@ -20,7 +20,7 @@ import (
|
||||
_ "embed"
|
||||
)
|
||||
|
||||
const VERSION = "v0.1.2";
|
||||
const VERSION = "v0.1.4";
|
||||
const LISTEN_HOST = "0.0.0.0";
|
||||
const DB_SCHEMA = 5
|
||||
|
||||
@ -31,7 +31,6 @@ var (
|
||||
config Config
|
||||
)
|
||||
|
||||
|
||||
func init() {// {{{
|
||||
flag.IntVar(
|
||||
&flagPort,
|
||||
@ -76,6 +75,7 @@ func main() {// {{{
|
||||
http.HandleFunc("/node/rename", nodeRename)
|
||||
http.HandleFunc("/node/delete", nodeDelete)
|
||||
http.HandleFunc("/node/upload", nodeUpload)
|
||||
http.HandleFunc("/node/download", nodeDownload)
|
||||
http.HandleFunc("/ws", websocketHandler)
|
||||
http.HandleFunc("/", staticHandler)
|
||||
|
||||
@ -443,6 +443,73 @@ func nodeUpload(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
"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) {// {{{
|
||||
var err error
|
||||
var session Session
|
||||
@ -461,7 +528,7 @@ func nodeFiles(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
return
|
||||
}
|
||||
|
||||
files, err = session.Files(req.NodeID)
|
||||
files, err = session.Files(req.NodeID, 0)
|
||||
if err != nil {
|
||||
responseError(w, err)
|
||||
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.Files, err = session.Files(node.ID)
|
||||
node.Files, err = session.Files(node.ID, 0)
|
||||
|
||||
return
|
||||
}// }}}
|
||||
|
@ -204,7 +204,7 @@ header .menu {
|
||||
#file-section {
|
||||
justify-self: center;
|
||||
width: 900px;
|
||||
margin-top: 32px;
|
||||
margin-top: 16px;
|
||||
padding: 32px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
@ -224,6 +224,10 @@ header .menu {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
cursor: pointer;
|
||||
}
|
||||
#file-section .files .filename:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
#file-section .files .size {
|
||||
white-space: nowrap;
|
||||
@ -232,13 +236,17 @@ header .menu {
|
||||
.tree {
|
||||
padding: 16px;
|
||||
}
|
||||
@media only screen and (max-width: 100ex) {
|
||||
@media only screen and (max-width: 932px) {
|
||||
.node-content {
|
||||
width: 100%;
|
||||
width: calc(100% - 32px);
|
||||
margin-left: 16px;
|
||||
padding: 16px;
|
||||
justify-self: start;
|
||||
}
|
||||
#file-section {
|
||||
width: 100%;
|
||||
width: calc(100% - 32px);
|
||||
padding: 16px;
|
||||
margin-left: 16px;
|
||||
justify-self: start;
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +226,7 @@ class NodeFiles extends Component {
|
||||
})
|
||||
.map(file=>
|
||||
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>
|
||||
`
|
||||
)
|
||||
@ -308,6 +308,37 @@ class Node {
|
||||
.then(callback)
|
||||
.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) {//{{{
|
||||
this.app.request('/node/tree', { StartNodeID: this.ID })
|
||||
.then(res=>{
|
||||
|
@ -240,7 +240,7 @@ header {
|
||||
#file-section {
|
||||
justify-self: center;
|
||||
width: 900px;
|
||||
margin-top: 32px;
|
||||
margin-top: 16px;
|
||||
padding: 32px;
|
||||
background: #f5f5f5;
|
||||
|
||||
@ -261,6 +261,11 @@ header {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.size {
|
||||
@ -274,14 +279,18 @@ header {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 100ex) {
|
||||
@media only screen and (max-width: 932px) {
|
||||
.node-content {
|
||||
width: 100%;
|
||||
width: calc(100% - 32px);
|
||||
margin-left: 16px;
|
||||
padding: 16px;
|
||||
justify-self: start;
|
||||
}
|
||||
|
||||
#file-section {
|
||||
width: 100%;
|
||||
width: calc(100% - 32px);
|
||||
padding: 16px;
|
||||
margin-left: 16px;
|
||||
justify-self: start;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user