mirror of https://github.com/anoshenko/rui.git
Added DownloadFile... functions
This commit is contained in:
parent
79fb34f29f
commit
a98d97ea8d
|
@ -1327,3 +1327,12 @@ function mediaSetVolume(elementId, volume) {
|
|||
element.volume = volume
|
||||
}
|
||||
}
|
||||
|
||||
function startDowndload(url, filename) {
|
||||
var element = document.getElementById("ruiDownloader");
|
||||
if (element) {
|
||||
element.href = url;
|
||||
element.setAttribute("download", filename);
|
||||
element.click();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
package rui
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed app_scripts.js
|
||||
|
@ -67,6 +71,7 @@ func (app *application) getStartPage() string {
|
|||
<body>
|
||||
<div class="ruiRoot" id="ruiRootView"></div>
|
||||
<div class="ruiPopupLayer" id="ruiPopupLayer" style="visibility: hidden;" onclick="clickOutsidePopup(event)"></div>
|
||||
<a id="ruiDownloader" download style="display: none;"></a>
|
||||
</body>
|
||||
</html>`)
|
||||
|
||||
|
@ -129,7 +134,8 @@ func (app *application) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||
filename = filename[:size-1]
|
||||
}
|
||||
|
||||
if !serveResourceFile(filename, w, req) {
|
||||
if !serveResourceFile(filename, w, req) &&
|
||||
!serveDownloadFile(filename, w, req) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
@ -295,3 +301,62 @@ func OpenBrowser(url string) bool {
|
|||
|
||||
return err != nil
|
||||
}
|
||||
|
||||
type downloadFile struct {
|
||||
filename string
|
||||
path string
|
||||
data []byte
|
||||
}
|
||||
|
||||
var currentDownloadId = int(rand.Int31())
|
||||
var downloadFiles = map[string]downloadFile{}
|
||||
|
||||
func (session *sessionData) startDownload(file downloadFile) {
|
||||
currentDownloadId++
|
||||
id := strconv.Itoa(currentDownloadId)
|
||||
downloadFiles[id] = file
|
||||
session.runScript(fmt.Sprintf(`startDowndload("%s", "%s")`, id, file.filename))
|
||||
}
|
||||
|
||||
func serveDownloadFile(id string, w http.ResponseWriter, r *http.Request) bool {
|
||||
if file, ok := downloadFiles[id]; ok {
|
||||
delete(downloadFiles, id)
|
||||
if file.data != nil {
|
||||
http.ServeContent(w, r, file.filename, time.Now(), bytes.NewReader(file.data))
|
||||
return true
|
||||
} else if _, err := os.Stat(file.path); err == nil {
|
||||
http.ServeFile(w, r, file.path)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DownloadFile starts downloading the file on the client side.
|
||||
func (session *sessionData) DownloadFile(path string) {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
ErrorLog(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, filename := filepath.Split(path)
|
||||
session.startDownload(downloadFile{
|
||||
filename: filename,
|
||||
path: path,
|
||||
data: nil,
|
||||
})
|
||||
}
|
||||
|
||||
// DownloadFileData starts downloading the file on the client side. Arguments specify the name of the downloaded file and its contents
|
||||
func (session *sessionData) DownloadFileData(filename string, data []byte) {
|
||||
if data == nil {
|
||||
ErrorLog("Invalid download data. Must be not nil.")
|
||||
return
|
||||
}
|
||||
|
||||
session.startDownload(downloadFile{
|
||||
filename: filename,
|
||||
path: "",
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,18 +6,24 @@ import (
|
|||
|
||||
const filePickerDemoText = `
|
||||
GridLayout {
|
||||
width = 100%, height = 100%, cell-height = "auto, 1fr",
|
||||
width = 100%, height = 100%, cell-height = "auto, 1fr", cell-width = "1fr, auto",
|
||||
content = [
|
||||
FilePicker {
|
||||
id = filePicker, accept = "txt, html"
|
||||
},
|
||||
Button {
|
||||
id = fileDownload, row = 0, column = 1, content = "Download file", disabled = true,
|
||||
}
|
||||
EditView {
|
||||
id = selectedFileData, row = 1, type = multiline, read-only = true, wrap = true,
|
||||
id = selectedFileData, row = 1, column = 0:1, type = multiline, read-only = true, wrap = true,
|
||||
}
|
||||
]
|
||||
}
|
||||
`
|
||||
|
||||
var downloadedFile []byte = nil
|
||||
var downloadedFilename = ""
|
||||
|
||||
func createFilePickerDemo(session rui.Session) rui.View {
|
||||
view := rui.CreateViewFromText(session, filePickerDemoText)
|
||||
if view == nil {
|
||||
|
@ -28,12 +34,20 @@ func createFilePickerDemo(session rui.Session) rui.View {
|
|||
if len(files) > 0 {
|
||||
picker.LoadFile(files[0], func(file rui.FileInfo, data []byte) {
|
||||
if data != nil {
|
||||
downloadedFile = data
|
||||
downloadedFilename = files[0].Name
|
||||
rui.Set(view, "selectedFileData", rui.Text, string(data))
|
||||
rui.Set(view, "fileDownload", rui.Disabled, false)
|
||||
} else {
|
||||
rui.Set(view, "selectedFileData", rui.Text, rui.LastError())
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
rui.Set(view, "fileDownload", rui.ClickEvent, func() {
|
||||
view.Session().DownloadFileData(downloadedFilename, downloadedFile)
|
||||
})
|
||||
|
||||
return view
|
||||
}
|
||||
|
|
|
@ -53,6 +53,9 @@ type Session interface {
|
|||
// a description of the error is written to the log
|
||||
Set(viewID, tag string, value interface{}) bool
|
||||
|
||||
DownloadFile(path string)
|
||||
DownloadFileData(filename string, data []byte)
|
||||
|
||||
registerAnimation(props []AnimatedProperty) string
|
||||
|
||||
resolveConstants(value string) (string, bool)
|
||||
|
|
Loading…
Reference in New Issue