Add export to CSV function

This commit is contained in:
2021-03-08 15:30:05 +01:00
parent f3f101d804
commit 2dd9ad4777
4 changed files with 128 additions and 23 deletions

2
go.mod
View File

@@ -16,7 +16,7 @@ require (
github.com/Fornaxian/config v0.0.0-20180915150834-ac41cf746a70
github.com/Fornaxian/log v0.0.0-20190617093801-1c7ce9a7c9b3
github.com/Fornaxian/pd_mime_type v0.0.0-20200204165508-2815edf3a145
github.com/google/uuid v1.1.1
github.com/google/uuid v1.2.0
github.com/julienschmidt/httprouter v1.3.0
github.com/microcosm-cc/bluemonday v1.0.4
github.com/russross/blackfriday/v2 v2.1.0

View File

@@ -35,6 +35,10 @@
</li>
</ul>
<a href="/user/settings" class="button button_highlight">Change account settings</a>
<br/><br/>
<a href="/user/export/files" class="button">Export uploaded files to CSV</a>
<a href="/user/export/lists" class="button">Export created lists to CSV</a>
<h2>Statistics</h2>
<p>

View File

@@ -0,0 +1,106 @@
package webcontroller
import (
"io"
"net/http"
"sort"
"strconv"
"strings"
"time"
"github.com/Fornaxian/log"
"github.com/julienschmidt/httprouter"
)
func writeCSVLine(w io.Writer, fields ...interface{}) {
for i, field := range fields {
if i != 0 {
w.Write([]byte(","))
}
switch val := field.(type) {
case string:
// In CSV files quotes are escaped by replacing them with double quotes
w.Write([]byte(`"` + strings.ReplaceAll(val, `"`, `""`) + `"`))
case int:
w.Write([]byte(strconv.Itoa(val)))
case int64:
w.Write([]byte(strconv.FormatInt(val, 10)))
case time.Time:
w.Write([]byte(`"` + val.Format(time.RFC3339) + `"`))
default:
panic("unknown CSV field type")
}
}
w.Write([]byte("\n"))
}
func (wc *WebController) serveUserExportFiles(
w http.ResponseWriter,
r *http.Request,
p httprouter.Params,
) {
td := wc.newTemplateData(w, r)
if !td.Authenticated {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
files, err := td.PixelAPI.UserFiles()
if err != nil {
log.Error("Failed to get user files: %s", err)
return
}
sort.Slice(files.Files, func(i, j int) (less bool) {
return files.Files[i].DateUpload.Before(files.Files[j].DateUpload)
})
w.Header().Add("Content-Description", "File Transfer")
w.Header().Add("Content-Disposition", `attachment; filename=pixeldrain_user_files.csv`)
w.Header().Add("Content-Type", "text/csv")
w.Header().Add("Transfer-Encoding", "chunked") // Replacement for Content-Length
writeCSVLine(
w, "id", "name", "size", "type", "date_upload", "date_last_view",
"views", "downloads", "bandwidth_used",
)
for _, file := range files.Files {
writeCSVLine(
w, file.ID, file.Name, file.Size, file.MimeType, file.DateUpload,
file.DateLastView, file.Views, file.Downloads, file.BandwidthUsed,
)
}
}
func (wc *WebController) serveUserExportLists(
w http.ResponseWriter,
r *http.Request,
p httprouter.Params,
) {
td := wc.newTemplateData(w, r)
if !td.Authenticated {
http.Redirect(w, r, "/login", http.StatusSeeOther)
return
}
lists, err := td.PixelAPI.UserLists()
if err != nil {
log.Error("Failed to get user lists: %s", err)
return
}
sort.Slice(lists.Lists, func(i, j int) (less bool) {
return lists.Lists[i].DateCreated.Before(lists.Lists[j].DateCreated)
})
w.Header().Add("Content-Description", "File Transfer")
w.Header().Add("Content-Disposition", `attachment; filename=pixeldrain_user_lists.csv`)
w.Header().Add("Content-Type", "text/csv")
w.Header().Add("Transfer-Encoding", "chunked") // Replacement for Content-Length
writeCSVLine(w, "id", "title", "date_created", "file_count")
for _, list := range lists.Lists {
writeCSVLine(w, list.ID, list.Title, list.DateCreated, list.FileCount)
}
}

View File

@@ -164,6 +164,8 @@ func New(
{GET, "user/lists" /* */, wc.serveTemplate("user_lists", true)},
{GET, "user/buckets" /* */, wc.serveTemplate("user_buckets", true)},
{GET, "user/filemanager" /* */, wc.serveTemplate("file_manager", true)},
{GET, "user/export/files" /**/, wc.serveUserExportFiles},
{GET, "user/export/lists" /**/, wc.serveUserExportLists},
// User account settings
{GET, "user/settings" /* */, wc.serveUserSettings},
@@ -200,15 +202,8 @@ func New(
return wc
}
func (wc *WebController) serveTemplate(
tpl string,
requireAuth bool,
) httprouter.Handle {
return func(
w http.ResponseWriter,
r *http.Request,
p httprouter.Params,
) {
func (wc *WebController) serveTemplate(tpl string, requireAuth bool) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
var tpld = wc.newTemplateData(w, r)
if requireAuth && !tpld.Authenticated {
http.Redirect(w, r, "/login", http.StatusSeeOther)