1diff --git a/pkg/service/filesystem.go b/pkg/service/filesystem.go
2index b4479ea3d5cea80dddb58e09f5265d3469f1964e..1364fd8deb7e0e01af4d4c509c07487ae7367e26 100644
3--- a/pkg/service/filesystem.go
4+++ b/pkg/service/filesystem.go
5@@ -85,24 +85,32 @@ }
6 return result
7 }
8
9-func (self *FileSystemController) GetPage(ctx context.Context, userID uint, filepath string) (*Page, error) {
10- userPath, err := self.userRepository.GetPathFromUserID(ctx, userID)
11+func (f *FileSystemController) GetFullpath(ctx context.Context, userID uint, filepath string) (string, error) {
12+ userPath, err := f.userRepository.GetPathFromUserID(ctx, userID)
13 if err != nil {
14- return nil, err
15+ return "", err
16 }
17- decodedPath, err := url.QueryUnescape(filepath)
18+
19+ return path.Join(userPath, filepath), nil
20+}
21+
22+func (f *FileSystemController) IsFile(ctx context.Context, fullPath string) (bool, error) {
23+ inf, err := f.fsRepository.Stat(fullPath)
24 if err != nil {
25- return nil, err
26+ return false, err
27 }
28
29- fullPath := path.Join(userPath, decodedPath)
30- files, err := self.fsRepository.List(fullPath)
31+ return !inf.IsDir(), nil
32+}
33+
34+func (f *FileSystemController) GetPage(ctx context.Context, filename string, fullPath string) (*Page, error) {
35+
36+ files, err := f.fsRepository.List(fullPath)
37 if err != nil {
38 return nil, err
39 }
40-
41 params := list.Map(files, func(info fs.FileInfo) *FileParam {
42- fullPath := path.Join(decodedPath, info.Name())
43+ fullPath := path.Join(filename, info.Name())
44 scapedFullPath := url.QueryEscape(fullPath)
45 return &FileParam{
46 Info: info,
47@@ -112,6 +120,6 @@ })
48
49 return &Page{
50 Files: params,
51- History: getHistory(decodedPath),
52+ History: getHistory(filename),
53 }, nil
54 }
55diff --git a/pkg/view/filesystem.go b/pkg/view/filesystem.go
56index 9071ec0e0cc95d53713c5e753d5a942539db8fec..f78f8a6b4196b3d58cf257351e0b59533251e11b 100644
57--- a/pkg/view/filesystem.go
58+++ b/pkg/view/filesystem.go
59@@ -1,7 +1,9 @@
60 package view
61
62 import (
63+ "mime"
64 "net/http"
65+ "path/filepath"
66
67 "git.sr.ht/~gabrielgio/img/pkg/database/repository"
68 "git.sr.ht/~gabrielgio/img/pkg/ext"
69@@ -37,7 +39,24 @@ pathValue = r.FormValue("path")
70 user = ext.GetUserFromCtx(r)
71 )
72
73- page, err := self.fsService.GetPage(r.Context(), user.ID, pathValue)
74+ fullpath, err := self.fsService.GetFullpath(r.Context(), user.ID, pathValue)
75+ if err != nil {
76+ return err
77+ }
78+
79+ isFile, err := self.fsService.IsFile(r.Context(), fullpath)
80+ if err != nil {
81+ return err
82+ }
83+
84+ if isFile {
85+ mimetype := mime.TypeByExtension(filepath.Ext(fullpath))
86+ w.Header().Set("Content-Type", mimetype)
87+ http.ServeFile(w, r, fullpath)
88+ return nil
89+ }
90+
91+ page, err := self.fsService.GetPage(r.Context(), pathValue, fullpath)
92 if err != nil {
93 return err
94 }
95diff --git a/templates/fs.qtpl b/templates/fs.qtpl
96index 3dc2c5ab5912b7c9241d8a7a49a1ad5a9cf6051d..7ffc39ccf85192650c3a9a2fcb5d2405878ca3ef 100644
97--- a/templates/fs.qtpl
98+++ b/templates/fs.qtpl
99@@ -25,11 +25,11 @@ <div class="column">
100 <span class="text-size-2">
101 {% if p.ShowMode %}{%s f.Info.Mode().String() %} {% endif %}
102 {% if p.ShowOwner %}{%d f.GetGid() %}:{%d f.GetUid() %} {% endif %}
103- {% if f.Info.IsDir() %}
104 </span>
105+ {% if f.Info.IsDir() %}
106 <a class="text-size-2" href="/?path={%s f.UrlEncodedPath %}">{%s f.Info.Name() %}/</a>
107 {% else %}
108- {%s f.Info.Name() %}
109+ <a class="text-size-2" href="/?path={%s f.UrlEncodedPath %}">{%s f.Info.Name() %}</a>
110 {% endif %}
111 </div>
112 <div class="column text-size-2 has-text-right">{%dl f.Info.Size() %} B</div>