21 Commits

Author SHA1 Message Date
0a70d99af5 changelog for 1.3.0 2020-07-25 12:35:26 +12:00
6720cbc0d9 upload: buffer MIME parsing on disk, not in memory 2020-07-25 12:25:44 +12:00
8d11b7c434 doc/README: add links for archived releases 2020-05-06 18:05:58 +12:00
147608a327 hg2git: fix source tarball generation in Makefile 2018-12-31 19:02:58 +13:00
951c87b63f convert to Go Modules 2018-12-31 19:02:50 +13:00
25180afaa2 doc: fix markdown syntax 2018-10-06 14:04:13 +13:00
33ca03b9d7 doc: update README for GFM syntax 2018-10-06 13:49:20 +13:00
b562ca4bd4 doc: move marketing images to /doc/ subdir 2018-10-06 13:49:00 +13:00
a25dc5827b doc: add image1.png thumbnail 2018-10-06 13:43:02 +13:00
5263f96956 doc: update readme 2018-09-09 19:03:29 +12:00
2b2add62b2 vcs: remove old hgtags 2018-09-09 18:45:14 +12:00
fdc93e6485 vcs: migrate hgignore->gitignore 2018-09-09 18:45:07 +12:00
b08f1c33d5 thumbs: allow configuring limit on simultanous thumbs (default 16) 2018-09-09 18:41:37 +12:00
524f37d9fe serve text/plain content with charset=utf-8 header 2018-09-09 18:33:33 +12:00
c958c57794 thumb: only generate one thumbnail concurrently 2018-09-09 18:31:25 +12:00
8fbad2a1e0 doc: move README to top-level, for web viewing 2018-07-21 13:38:46 +12:00
989cd195f8 doc: remove TODO file
Issues are now tracked at git.ivysaur.me.
2018-07-21 13:36:14 +12:00
cb4933fa72 doc: update TODO 2018-07-10 17:45:58 +12:00
f504ab5929 bump version to 1.2.2 2018-06-09 18:13:22 +12:00
f8e95a8037 add go-get tags to readme 2018-06-09 18:12:50 +12:00
feaa51cfcd Added tag v1.2.1 for changeset 7c3807929e7a 2018-06-09 18:11:39 +12:00
16 changed files with 117 additions and 155 deletions

View File

@@ -1,5 +1,3 @@
syntax: glob
cmd/contented/contented cmd/contented/contented
build/ build/
_dist/ _dist/

12
.hgtags
View File

@@ -1,12 +0,0 @@
e2250a7fd29052ea767f18e1459cabea4cd7efd3 v1.0.0
b8975b9e75648a7c2a5003c67db92cf2216e01c0 v1.0.1
c7b699105bd166e7a01aa0e678d34624680bf81e v1.1.0
c7b699105bd166e7a01aa0e678d34624680bf81e v1.1.0
0000000000000000000000000000000000000000 v1.1.0
0000000000000000000000000000000000000000 v1.1.0
cfb1e028fd0627614aa01184893f9f29f20a347e v1.1.0
cfb1e028fd0627614aa01184893f9f29f20a347e v1.1.0
0000000000000000000000000000000000000000 v1.1.0
0000000000000000000000000000000000000000 v1.1.0
98da2ebf0d50dffe8b625457a639bc2f15519714 v1.1.0
0f021da52854175cd48084249c45b1d3fa8b58ca v1.2.0

57
Gopkg.lock generated
View File

@@ -1,57 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
branch = "master"
name = "code.ivysaur.me/imagequant"
packages = ["."]
revision = "6a468707fb1bb44c4bb71113273cc73daf401976"
[[projects]]
branch = "master"
name = "code.ivysaur.me/thumbnail"
packages = ["."]
revision = "13e0990a33026cba5f746c13c85782e562e61fa6"
[[projects]]
name = "github.com/boltdb/bolt"
packages = ["."]
revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8"
version = "v1.3.1"
[[projects]]
branch = "master"
name = "github.com/hashicorp/golang-lru"
packages = [".","simplelru"]
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
[[projects]]
branch = "master"
name = "github.com/mxk/go-flowrate"
packages = ["flowrate"]
revision = "cca7078d478f8520f85629ad7c68962d31ed7682"
[[projects]]
name = "github.com/speps/go-hashids"
packages = ["."]
revision = "d1d57a886aa7e3ef6092b70ceab077e35ee8e0ce"
version = "v1.0.0"
[[projects]]
branch = "master"
name = "golang.org/x/image"
packages = ["bmp","draw","math/f64","riff","vp8","vp8l","webp"]
revision = "af66defab954cb421ca110193eed9477c8541e2a"
[[projects]]
branch = "master"
name = "golang.org/x/sys"
packages = ["unix"]
revision = "9527bec2660bd847c050fda93a0f0c6dee0800bb"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "907370ab34b6a574b2845b17f9033acb75dfc5c8348266167f95f0112f38e89a"
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,38 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "code.ivysaur.me/thumbnail"
branch = "master"
[[constraint]]
name = "github.com/boltdb/bolt"
version = "1.3.1"
[[constraint]]
branch = "master"
name = "github.com/mxk/go-flowrate"
[[constraint]]
name = "github.com/speps/go-hashids"
version = "1.0.0"

View File

@@ -2,7 +2,7 @@
# Makefile for contented # Makefile for contented
# #
VERSION:=1.2.1 VERSION:=1.2.2
SOURCES:=Makefile \ SOURCES:=Makefile \
static \ static \
@@ -69,5 +69,5 @@ _dist/contented-$(VERSION)-win32.7z: build/win32/contented.exe
) )
_dist/contented-$(VERSION)-src.zip: $(SOURCES) _dist/contented-$(VERSION)-src.zip: $(SOURCES)
hg archive --type=zip _dist/contented-$(VERSION)-src.zip git archive HEAD -o _dist/contented-$(VERSION)-src.zip

View File

@@ -1,15 +1,17 @@
A file / image / paste upload server with a focus on embedding. # contented
Written in Go [![](doc/image1.thumb.png)](doc/image1.png)
A file / image / paste upload server with a focus on embedding.
You can use contented as a standalone upload server, or you can use the SDK to embed its upload widget into another website. You can use contented as a standalone upload server, or you can use the SDK to embed its upload widget into another website.
=FEATURES= ## Features
- Drag and drop upload - Drag and drop upload
- Multiple files upload - Multiple files upload
- Pastebin upload - Pastebin upload
- Custom drawing upload ([url=https://github.com/Leimi/drawingboard.js]via[/url]) - Custom drawing upload ([via drawingboard.js](https://github.com/Leimi/drawingboard.js))
- Ctrl-V upload - Ctrl-V upload
- SDK-oriented design for embedding, including CORS support - SDK-oriented design for embedding, including CORS support
- Mobile friendly HTML interface - Mobile friendly HTML interface
@@ -17,12 +19,13 @@ You can use contented as a standalone upload server, or you can use the SDK to e
- Hash verification (SHA512/256) - Hash verification (SHA512/256)
- Detect duplicate upload content and reuse storage - Detect duplicate upload content and reuse storage
- Options to limit the upload filesize and the upload bandwidth - Options to limit the upload filesize and the upload bandwidth
- Short URLs (using [url=http://hashids.org]Hashids[/url] algorithm) - Short URLs (using [Hashids](http://hashids.org) algorithm)
- Image thumbnailing - Image thumbnailing
=USAGE (SERVER)= ## Usage (Server)
`Usage of contented: ```
Usage of contented:
-data string -data string
Directory for stored content (default "") Directory for stored content (default "")
-db string -db string
@@ -41,39 +44,55 @@ You can use contented as a standalone upload server, or you can use the SDK to e
Title used in web interface (default "contented") Title used in web interface (default "contented")
-trustXForwardedFor -trustXForwardedFor
Trust X-Forwarded-For reverse proxy headers Trust X-Forwarded-For reverse proxy headers
` -concurrentthumbs
Simultaneous thumbnail generation (default 16)
```
If you are hosting behind a reverse proxy, remember to set its post body size parameter appropriately (e.g. `client_max_body_size` for nginx). If you are hosting behind a reverse proxy, remember to set its post body size parameter appropriately (e.g. `client_max_body_size` for nginx).
=USAGE (HTTP)= ## Usage (HTTP)
The server responds on the following URLs: The server responds on the following URLs:
- `/get/{ID}`: Download item content URL |Method |Description
- `/info/{ID}`: Get item content metadata (JSON) ---------------------|-------|---
- `/thumb/{Type}/{ID}`: Get item thumbnail image `/get/{ID}` |`GET` |Download item content
- `/about`: Get server metadata (JSON) `/info/{ID}` |`GET` |Get item content metadata (JSON)
`/thumb/{Type}/{ID}` |`GET` |Get item thumbnail image
`/about` |`GET` |Get server metadata (JSON)
=USAGE (EMBEDDING FOR WEB)= ## Usage (Embedding for web)
Your webpage should load the SDK from the contented server, then call the `contented.init` function to display the upload widget over the top of an existing DOM element. Your callback will be passed an array of file IDs of any uploaded items. Your webpage should load the SDK from the contented server, then call the `contented.init` function to display the upload widget over the top of an existing DOM element. Your callback will be passed an array of file IDs of any uploaded items.
`<script type="text/javascript" src="SERVER_ADDR/sdk.js"></script> ```html
<script type="text/javascript" src="SERVER_ADDR/sdk.js"></script>
contented.init("#target", function(/* String[] */ items) {}); contented.init("#target", function(/* String[] */ items) {});
` ```
=CHANGELOG= ## Changelog
2020-07-25: 1.3.0
- Feature: Option to limit concurrent thumbnail generation
- Enhancement: Set charset=UTF-8 when serving user-submitted text/plain content
- Fix an issue with large memory usage for multipart file uploads
2018-06-09: 1.2.1 2018-06-09: 1.2.1
- Feature: Add OpenGraph tags on preview pages, for rich metadata in chat applications - Feature: Add OpenGraph tags on preview pages, for rich metadata in chat applications
- Update thumbnailing library to improve quality - Update thumbnailing library to improve quality
- Use dep for vendoring - Use dep for vendoring
- [⬇️ contented-1.2.1-win32.7z](https://git.ivysaur.me/attachments/88dea4f7-e314-4325-a957-096dcf8cdecc) *(1.51 MiB)*
- [⬇️ contented-1.2.1-src.zip](https://git.ivysaur.me/attachments/6fd2b963-3be4-48a6-a5bf-6f273bcaea24) *(1.49 MiB)*
- [⬇️ contented-1.2.1-linux64.tar.gz](https://git.ivysaur.me/attachments/c536f764-0250-4d67-886a-4797946e1124) *(2.21 MiB)*
2017-11-18: 1.2.0 2017-11-18: 1.2.0
- Feature: Thumbnail support - Feature: Thumbnail support
- Feature: File preview page - Feature: File preview page
- Feature: Album mode (via URL `/p/{file1}-{file2}-...`) - Feature: Album mode (via URL `/p/{file1}-{file2}-...`)
- Feature: New `-diskFilesWorldReadable` option to save files with `0644` mode - Feature: New `-diskFilesWorldReadable` option to save files with `0644` mode
- [⬇️ contented-1.2.0-win32.7z](https://git.ivysaur.me/attachments/f3453b62-b2a7-4e77-9b04-44c99dec35ba) *(1.36 MiB)*
- [⬇️ contented-1.2.0-src.zip](https://git.ivysaur.me/attachments/a6c1ecfb-fd6a-44b5-9dc8-aea7c439d1e6) *(178.94 KiB)*
- [⬇️ contented-1.2.0-linux64.tar.gz](https://git.ivysaur.me/attachments/6234754b-af17-4a72-8b66-56a5db21c7c7) *(2.03 MiB)*
2017-10-15: 1.1.0 2017-10-15: 1.1.0
- Feature: Drawing mode - Feature: Drawing mode
@@ -87,11 +106,20 @@ contented.init("#target", function(/* String[] */ items) {});
- Include drawingboard.js 0.4.6 (MIT license) - Include drawingboard.js 0.4.6 (MIT license)
- Fix a cosmetic issue with javascript console output - Fix a cosmetic issue with javascript console output
- Fix a cosmetic issue with error messages if an upload failed - Fix a cosmetic issue with error messages if an upload failed
- [⬇️ contented-1.1.0-win32.7z](https://git.ivysaur.me/attachments/bfb0a7fe-bf95-4d0e-933b-8137bc8071a4) *(1.11 MiB)*
- [⬇️ contented-1.1.0-src.zip](https://git.ivysaur.me/attachments/67401341-724f-4ea2-b9c7-44d08ab9d38a) *(142.82 KiB)*
- [⬇️ contented-1.1.0-linux64.tar.gz](https://git.ivysaur.me/attachments/a13752dd-5228-4830-b61d-0f7cc568b2ae) *(1.67 MiB)*
2017-10-08: 1.0.1 2017-10-08: 1.0.1
- Fix an issue with CORS preflight requests - Fix an issue with CORS preflight requests
- Fix an issue with index URLs - Fix an issue with index URLs
- [⬇️ contented-1.0.1-win32.7z](https://git.ivysaur.me/attachments/a873d510-da09-4797-95e9-ffcad690a77b) *(1.10 MiB)*
- [⬇️ contented-1.0.1-src.zip](https://git.ivysaur.me/attachments/43ac17d6-b6f1-4da7-98e9-b8af6fb5551a) *(109.08 KiB)*
- [⬇️ contented-1.0.1-linux64.tar.gz](https://git.ivysaur.me/attachments/34d74bed-db3f-4cef-a76f-266f0b9e6017) *(1.65 MiB)*
2017-10-08: 1.0.0 2017-10-08: 1.0.0
- Initial public release - Initial public release
- Include jQuery 1.12.4 (MIT license) - Include jQuery 1.12.4 (MIT license)
- [⬇️ contented-1.0.0-win32.7z](https://git.ivysaur.me/attachments/4ef132cf-dac8-4bcf-9da7-14ca1366e815) *(1.10 MiB)*
- [⬇️ contented-1.0.0-src.zip](https://git.ivysaur.me/attachments/74d77b3f-557b-44bf-9645-7b3b25ab17c1) *(102.45 KiB)*
- [⬇️ contented-1.0.0-linux64.tar.gz](https://git.ivysaur.me/attachments/1c28a913-686b-44cf-b63d-db22968a93b6) *(1.65 MiB)*

View File

@@ -16,6 +16,8 @@ import (
var SERVER_HEADER string = `contented/0.0.0-dev` var SERVER_HEADER string = `contented/0.0.0-dev`
const DEFAULT_MAX_CONCURRENT_THUMBS = 16
type ServerPublicProperties struct { type ServerPublicProperties struct {
AppTitle string AppTitle string
MaxUploadBytes int64 MaxUploadBytes int64
@@ -29,6 +31,7 @@ type ServerOptions struct {
BandwidthLimit int64 BandwidthLimit int64
TrustXForwardedFor bool TrustXForwardedFor bool
EnableHomepage bool EnableHomepage bool
MaxConcurrentThumbs int
ServerPublicProperties ServerPublicProperties
} }
@@ -44,6 +47,7 @@ type Server struct {
opts ServerOptions opts ServerOptions
db *bolt.DB db *bolt.DB
startTime time.Time startTime time.Time
thumbnailSem chan struct{}
metadataBucket []byte metadataBucket []byte
} }
@@ -54,6 +58,17 @@ func NewServer(opts *ServerOptions) (*Server, error) {
startTime: time.Now(), startTime: time.Now(),
} }
if s.opts.MaxConcurrentThumbs <= 0 {
s.opts.MaxConcurrentThumbs = DEFAULT_MAX_CONCURRENT_THUMBS // default
log.Printf("Allowing %d concurrent thumbnails", s.opts.MaxConcurrentThumbs)
}
// "fill" the thumbnailer semaphore
s.thumbnailSem = make(chan struct{}, s.opts.MaxConcurrentThumbs)
for i := 0; i < s.opts.MaxConcurrentThumbs; i += 1 {
s.thumbnailSem <- struct{}{}
}
b, err := bolt.Open(opts.DBPath, 0644, bolt.DefaultOptions) b, err := bolt.Open(opts.DBPath, 0644, bolt.DefaultOptions)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -1,22 +0,0 @@
TODO
- View server-wide recent uploads history / all upload history
- Display 'my uploads' (id + metadata history kept in localstorage)
- Encrypted at rest (anti- provider snooping)
- Prevent selecting around the toggle buttons (firefox for android)
- Detect when pasting creates one large file and one ~150 byte file(?? why does this happen?)
- Detect when pasting an image URL, offer to download it (clientside?)
- Add caching headers on thumbnails and on content endpoints
- Add content-security headers on html pages
- If file is larger than the upload limit, warn before the upload happens
- If multiple files are larger than the upload limit, break into multiple uploads

View File

@@ -21,6 +21,7 @@ func main() {
trustXForwardedFor := flag.Bool("trustXForwardedFor", false, "Trust X-Forwarded-For reverse proxy headers") trustXForwardedFor := flag.Bool("trustXForwardedFor", false, "Trust X-Forwarded-For reverse proxy headers")
enableHomepage := flag.Bool("enableHomepage", true, "Enable homepage (disable for embedded use only)") enableHomepage := flag.Bool("enableHomepage", true, "Enable homepage (disable for embedded use only)")
diskFilesWorldReadable := flag.Bool("diskFilesWorldReadable", false, "Save files as 0644 instead of 0600") diskFilesWorldReadable := flag.Bool("diskFilesWorldReadable", false, "Save files as 0644 instead of 0600")
maxConcurrentThumbs := flag.Int("concurrentthumbs", contented.DEFAULT_MAX_CONCURRENT_THUMBS, "Simultaneous thumbnail generation")
flag.Parse() flag.Parse()
@@ -31,6 +32,7 @@ func main() {
TrustXForwardedFor: *trustXForwardedFor, TrustXForwardedFor: *trustXForwardedFor,
EnableHomepage: *enableHomepage, EnableHomepage: *enableHomepage,
DiskFilesWorldReadable: *diskFilesWorldReadable, DiskFilesWorldReadable: *diskFilesWorldReadable,
MaxConcurrentThumbs: *maxConcurrentThumbs,
ServerPublicProperties: contented.ServerPublicProperties{ ServerPublicProperties: contented.ServerPublicProperties{
AppTitle: *appTitle, AppTitle: *appTitle,
MaxUploadBytes: int64(*maxUploadMb) * 1024 * 1024, MaxUploadBytes: int64(*maxUploadMb) * 1024 * 1024,

View File

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

BIN
doc/image1.thumb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -37,9 +37,17 @@ func (this *Server) handleViewInternal(w http.ResponseWriter, r *http.Request, f
// ServeContent only uses the filename to get the mime type, which we can // ServeContent only uses the filename to get the mime type, which we can
// set accurately (including blacklist) // set accurately (including blacklist)
w.Header().Set(`Content-Type`, m.MimeType)
if m.MimeType == `application/octet-stream` { switch m.MimeType {
case `text/plain`:
w.Header().Set(`Content-Type`, `text/plain; charset=UTF-8`)
case `application/octet-stream`:
w.Header().Set(`Content-Type`, m.MimeType)
w.Header().Set(`Content-Disposition`, `attachment; filename="`+m.Filename+`"`) w.Header().Set(`Content-Disposition`, `attachment; filename="`+m.Filename+`"`)
default:
w.Header().Set(`Content-Type`, m.MimeType)
} }
http.ServeContent(w, r, "", m.UploadTime, f) http.ServeContent(w, r, "", m.UploadTime, f)

12
go.mod Normal file
View File

@@ -0,0 +1,12 @@
module code.ivysaur.me/contented
require (
code.ivysaur.me/imagequant v2.12.2-go1.2+incompatible
code.ivysaur.me/thumbnail v1.0.1
github.com/boltdb/bolt v1.3.1
github.com/hashicorp/golang-lru v0.5.0
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f
github.com/speps/go-hashids v1.0.0
golang.org/x/image v0.0.0-20180601115456-af66defab954
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b
)

16
go.sum Normal file
View File

@@ -0,0 +1,16 @@
code.ivysaur.me/imagequant v0.0.0-20180609052806-6a468707fb1b/go.mod h1:1Pi+M0oJFDYLtGuCkPGPpb4OGCYudvp/SG6jdVcO+WU=
code.ivysaur.me/imagequant v2.12.2-go1.2+incompatible/go.mod h1:1Pi+M0oJFDYLtGuCkPGPpb4OGCYudvp/SG6jdVcO+WU=
code.ivysaur.me/thumbnail v1.0.1 h1:vBvueRPu9Ed+PuULNdn0pbfmtt6SVNHJ+8ezZBl8pIg=
code.ivysaur.me/thumbnail v1.0.1/go.mod h1:oOapO2ddhCg0OBnAMFOW98mSKg6cRpWqCivVFcQnn5A=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/speps/go-hashids v1.0.0 h1:jdFC07PrExRM4Og5Ev4411Tox75aFpkC77NlmutadNI=
github.com/speps/go-hashids v1.0.0/go.mod h1:P7hqPzMdnZOfyIk+xrlG1QaSMw+gCBdHKsBDnhpaZvc=
golang.org/x/image v0.0.0-20180601115456-af66defab954 h1:n7UB+yxe5jyWxOA3BTAfwi23lhfKEIddaB/so7YOYe0=
golang.org/x/image v0.0.0-20180601115456-af66defab954/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

View File

@@ -1,6 +1,7 @@
package contented package contented
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"log" "log"
@@ -51,6 +52,8 @@ func getThumbnailerConfig(t byte) (*thumbnail.Config, error) {
} }
func (this *Server) handleThumb(w http.ResponseWriter, r *http.Request, thumbnailType byte, fileId string) { func (this *Server) handleThumb(w http.ResponseWriter, r *http.Request, thumbnailType byte, fileId string) {
ctx := r.Context()
opts, err := getThumbnailerConfig(thumbnailType) opts, err := getThumbnailerConfig(thumbnailType)
if err != nil { if err != nil {
log.Printf("%s Thumbnail failed: %s\n", this.remoteIP(r), err.Error()) log.Printf("%s Thumbnail failed: %s\n", this.remoteIP(r), err.Error())
@@ -58,9 +61,18 @@ func (this *Server) handleThumb(w http.ResponseWriter, r *http.Request, thumbnai
return return
} }
// Only a limited number of thumbnails can be generated concurrently
<-this.thumbnailSem
defer func() { this.thumbnailSem <- struct{}{} }()
if ctx.Err() != nil {
// The request was already cancelled
return
}
t := thumbnail.NewThumbnailerEx(opts) t := thumbnail.NewThumbnailerEx(opts)
err = this.handleThumbInternal(w, t, fileId) err = this.handleThumbInternal(ctx, w, t, fileId)
if err != nil { if err != nil {
log.Printf("%s Thumbnail failed: %s\n", this.remoteIP(r), err.Error()) log.Printf("%s Thumbnail failed: %s\n", this.remoteIP(r), err.Error())
@@ -69,7 +81,7 @@ func (this *Server) handleThumb(w http.ResponseWriter, r *http.Request, thumbnai
} }
} }
func (this *Server) handleThumbInternal(w http.ResponseWriter, t thumbnail.Thumbnailer, fileId string) error { func (this *Server) handleThumbInternal(ctx context.Context, w http.ResponseWriter, t thumbnail.Thumbnailer, fileId string) error {
// Load metadata // Load metadata
m, err := this.Metadata(fileId) m, err := this.Metadata(fileId)

View File

@@ -20,7 +20,7 @@ func (this *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
remoteIP := this.remoteIP(r) remoteIP := this.remoteIP(r)
err := r.ParseMultipartForm(this.opts.MaxUploadBytes * 2) err := r.ParseMultipartForm(0) // buffer upload in temporary files on disk, not memory
if err != nil { if err != nil {
log.Printf("%s Invalid request: %s\n", remoteIP, err.Error()) log.Printf("%s Invalid request: %s\n", remoteIP, err.Error())
http.Error(w, "Invalid request", 400) http.Error(w, "Invalid request", 400)