2017-12-31 01:32:28 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/md5"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2020-09-02 12:44:19 +02:00
|
|
|
"path/filepath"
|
2017-12-31 01:32:28 +01:00
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
2019-10-25 00:27:02 +02:00
|
|
|
"github.com/kataras/iris/v12"
|
2017-12-31 01:32:28 +01:00
|
|
|
)
|
|
|
|
|
2018-04-28 13:48:09 +02:00
|
|
|
const maxSize = 5 << 20 // 5MB
|
|
|
|
|
2017-12-31 01:32:28 +01:00
|
|
|
func main() {
|
|
|
|
app := iris.New()
|
|
|
|
|
|
|
|
app.RegisterView(iris.HTML("./templates", ".html"))
|
|
|
|
|
|
|
|
// Serve the upload_form.html to the client.
|
|
|
|
app.Get("/upload", func(ctx iris.Context) {
|
|
|
|
// create a token (optionally).
|
|
|
|
|
|
|
|
now := time.Now().Unix()
|
|
|
|
h := md5.New()
|
|
|
|
io.WriteString(h, strconv.FormatInt(now, 10))
|
|
|
|
token := fmt.Sprintf("%x", h.Sum(nil))
|
|
|
|
|
|
|
|
// render the form with the token for any use you'd like.
|
|
|
|
// ctx.ViewData("", token)
|
|
|
|
// or add second argument to the `View` method.
|
|
|
|
// Token will be passed as {{.}} in the template.
|
|
|
|
ctx.View("upload_form.html", token)
|
|
|
|
})
|
|
|
|
|
2018-04-28 13:48:09 +02:00
|
|
|
/* Read before continue.
|
2017-12-31 01:32:28 +01:00
|
|
|
|
2018-04-28 13:48:09 +02:00
|
|
|
0. The default post max size is 32MB,
|
|
|
|
you can extend it to read more data using the `iris.WithPostMaxMemory(maxSize)` configurator at `app.Run`,
|
|
|
|
note that this will not be enough for your needs, read below.
|
|
|
|
|
|
|
|
1. The faster way to check the size is using the `ctx.GetContentLength()` which returns the whole request's size
|
|
|
|
(plus a logical number like 2MB or even 10MB for the rest of the size like headers). You can create a
|
|
|
|
middleware to adapt this to any necessary handler.
|
|
|
|
|
|
|
|
myLimiter := func(ctx iris.Context) {
|
|
|
|
if ctx.GetContentLength() > maxSize { // + 2 << 20 {
|
|
|
|
ctx.StatusCode(iris.StatusRequestEntityTooLarge)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
ctx.Next()
|
|
|
|
}
|
|
|
|
|
|
|
|
app.Post("/upload", myLimiter, myUploadHandler)
|
|
|
|
|
|
|
|
Most clients will set the "Content-Length" header (like browsers) but it's always better to make sure that any client
|
|
|
|
can't send data that your server can't or doesn't want to handle. This can be happen using
|
|
|
|
the `app.Use(LimitRequestBodySize(maxSize))` (as app or route middleware)
|
|
|
|
or the `ctx.SetMaxRequestBodySize(maxSize)` to limit the request based on a customized logic inside a particular handler, they're the same,
|
|
|
|
read below.
|
|
|
|
|
|
|
|
2. You can force-limit the request body size inside a handler using the `ctx.SetMaxRequestBodySize(maxSize)`,
|
|
|
|
this will force the connection to close if the incoming data are larger (most clients will receive it as "connection reset"),
|
|
|
|
use that to make sure that the client will not send data that your server can't or doesn't want to accept, as a fallback.
|
|
|
|
|
|
|
|
app.Post("/upload", iris.LimitRequestBodySize(maxSize), myUploadHandler)
|
|
|
|
|
|
|
|
OR
|
|
|
|
|
|
|
|
app.Post("/upload", func(ctx iris.Context){
|
|
|
|
ctx.SetMaxRequestBodySize(maxSize)
|
|
|
|
|
|
|
|
// [...]
|
|
|
|
})
|
|
|
|
|
|
|
|
3. Another way is to receive the data and check the second return value's `Size` value of the `ctx.FormFile`, i.e `info.Size`, this will give you
|
|
|
|
the exact file size, not the whole incoming request data length.
|
|
|
|
|
|
|
|
app.Post("/", func(ctx iris.Context){
|
2017-12-31 01:32:28 +01:00
|
|
|
file, info, err := ctx.FormFile("uploadfile")
|
2018-04-28 13:48:09 +02:00
|
|
|
if err != nil {
|
|
|
|
ctx.StatusCode(iris.StatusInternalServerError)
|
|
|
|
ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
defer file.Close()
|
2017-12-31 01:32:28 +01:00
|
|
|
|
2018-04-28 13:48:09 +02:00
|
|
|
if info.Size > maxSize {
|
|
|
|
ctx.StatusCode(iris.StatusRequestEntityTooLarge)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// [...]
|
|
|
|
})
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Handle the post request from the upload_form.html to the server
|
|
|
|
app.Post("/upload", iris.LimitRequestBodySize(maxSize+1<<20), func(ctx iris.Context) {
|
|
|
|
// Get the file from the request.
|
2020-09-02 12:44:19 +02:00
|
|
|
f, fh, err := ctx.FormFile("uploadfile")
|
2017-12-31 01:32:28 +01:00
|
|
|
if err != nil {
|
|
|
|
ctx.StatusCode(iris.StatusInternalServerError)
|
|
|
|
ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
|
|
|
|
return
|
|
|
|
}
|
2020-09-02 12:44:19 +02:00
|
|
|
defer f.Close()
|
2017-12-31 01:32:28 +01:00
|
|
|
|
2020-09-02 12:44:19 +02:00
|
|
|
_, err = ctx.SaveFormFile(fh, filepath.Join("./uploads", fh.Filename))
|
2017-12-31 01:32:28 +01:00
|
|
|
if err != nil {
|
|
|
|
ctx.StatusCode(iris.StatusInternalServerError)
|
|
|
|
ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2018-04-28 13:48:09 +02:00
|
|
|
// start the server at http://localhost:8080 with post limit at 5 MB.
|
2020-03-05 21:41:27 +01:00
|
|
|
app.Listen(":8080" /* 0.*/, iris.WithPostMaxMemory(maxSize))
|
2017-12-31 01:32:28 +01:00
|
|
|
}
|