Use chunked uploads instead of single upload (#68)

* Change to chunked uploads

* Renamed SHA256 attribute to SHA1

* Breaking: removed /upload endpoint

* Changed timeout to 15 minutes for reading

* Change session key only after 12 hours

* Added API calls for chunk upload, refactoring, added tests

* Add content-type based on file extension for images if empty
This commit is contained in:
Marc Ole Bulling
2022-07-25 13:21:38 +02:00
committed by GitHub
parent 063c8c6798
commit 44260f012b
41 changed files with 2040 additions and 598 deletions

View File

@@ -56,13 +56,89 @@
}
}
},
"/chunk/add": {
"post": {
"tags": [
"files"
],
"summary": "Uploads a new chunk",
"description": "Uploads a file in chunks, in case a reverse proxy does not support upload of larger files. Parallel uploading is supported. Must call /chunk/complete after all chunks have been uploaded.",
"operationId": "chunkadd",
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/chunking"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Operation successful",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/chunkUploadResult"
}
}
}
},
"400": {
"description": "Invalid input"
},
"401": {
"description": "Invalid API key provided or not logged in as admin"
}
}
}
},
"/chunk/complete": {
"post": {
"tags": [
"files"
],
"summary": "Finalises uploaded chunks",
"description": "Needs to be called after all chunks have been uploaded. Adds the uploaded file to Gokapi.",
"operationId": "chunkcomplete",
"requestBody": {
"content": {
"application/x-www-form-urlencoded": {
"schema": {
"$ref": "#/components/schemas/chunkingcomplete"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Operation successful",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UploadResult"
}
}
}
},
"400": {
"description": "Invalid input"
},
"401": {
"description": "Invalid API key provided or not logged in as admin"
}
}
}
},
"/files/add": {
"post": {
"tags": [
"files"
],
"summary": "Adds a new file",
"description": "This API call uploads the submitted file to Gokapi",
"summary": "Adds a new file without chunking",
"description": "Uploads the submitted file to Gokapi. Please note: This method does not use chunking, therefore if you are behind a reverse proxy or have a provider that limits upload filesizes, this might not work for bigger files (e.g. Cloudflare).",
"operationId": "add",
"requestBody": {
"content": {
@@ -226,9 +302,6 @@
"Size": {
"type": "string"
},
"SHA256": {
"type": "string"
},
"HotlinkId": {
"type": "string"
},
@@ -272,19 +345,32 @@
"description": "File is a struct used for saving information about an uploaded file",
"x-go-package": "Gokapi/internal/models"
},
"chunkUploadResult": {
"type": "object",
"properties": {
"Result": {
"type": "string"
}
},
"description": "Result after uploading a chunk",
"x-go-package": "Gokapi/internal/models"
},
"UploadResult": {
"type": "object",
"properties": {
"Result": {
"type": "string"
},
"FileInfo": {
"$ref": "#/components/schemas/File"
},
"HotlinkUrl": {
"type": "string"
},
"Result": {
"Url": {
"type": "string"
},
"Url": {
"GenericHotlinkUrl": {
"type": "string"
}
},
@@ -346,6 +432,65 @@
"description": "Sets a new filename. Filename will be unchanged if empty."
}
}
},"chunking": {
"required": [
"file","uuid","filesize","offset"
],
"type": "object",
"properties": {
"file": {
"type": "string",
"description": "The file to be uploaded",
"format": "binary"
},
"uuid": {
"type": "string",
"description": "A unique ID that has to be the same for all chunks of a single file. Needs to be at least 10 characters long.",
},
"filesize": {
"type": "integer",
"description": "The total filesize of the final file in bytes"
},
"offset": {
"type": "integer",
"description": "The chunk's offset starting at the beginning of the file"
}
}
},"chunkingcomplete": {
"required": [
"uuid","filename","filesize"
],
"type": "object",
"properties": {
"uuid": {
"type": "string",
"description": "The unique ID that was used for the uploaded chunks",
},
"filename": {
"type": "string",
"description": "The filename of the uploaded file",
},
"filesize": {
"type": "integer",
"description": "The total filesize of the uploaded file in bytes"
},
"contenttype": {
"type": "string",
"description": "The MIME content type. If empty, application/octet-stream will be used."
},
"allowedDownloads": {
"type": "integer",
"description": "How many downloads are allowed. Last used value from web interface will be used if empty. Unlimited if 0 is passed."
},
"expiryDays": {
"type": "integer",
"description": "How many days the file will be stored. Last used value from web interface will be used if empty. Unlimited if 0 is passed."
},
"password": {
"type": "string",
"description": "Password for this file to be set. No password will be used if empty"
}
}
}
},
"securitySchemes": {