This commit is contained in:
lin onetwo 2025-12-02 14:33:57 +01:00 committed by GitHub
commit a6bb9a4caa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 96 additions and 0 deletions

View file

@ -0,0 +1,51 @@
/*\
title: $:/core/modules/server/routes/put-file.js
type: application/javascript
module-type: route
PUT /files/:filepath
\*/
"use strict";
exports.method = "PUT";
exports.path = /^\/files\/(.+)$/;
exports.bodyFormat = "stream";
exports.handler = function(request,response,state) {
var path = require("path"),
fs = require("fs"),
filename = $tw.utils.decodeURIComponentSafe(state.params[0]),
basePath = path.resolve(state.boot.wikiPath,"files"),
fullPath = path.resolve(basePath,filename);
// Check that the filename is inside the wiki files folder
if(path.relative(basePath,fullPath).indexOf("..") === 0) {
return state.sendResponse(404,{"Content-Type": "text/plain"},"File '" + filename + "' not found");
}
// Create directory if needed
fs.mkdir(path.dirname(fullPath),{recursive: true},function(err) {
if(err && err.code !== "EEXIST") {
$tw.utils.error("Error creating directory for file " + fullPath + ": " + err.toString());
return state.sendResponse(500,{"Content-Type": "text/plain"},"Directory error");
}
var stream = fs.createWriteStream(fullPath);
stream.on("error", function(err) {
$tw.utils.error("Error writing file " + fullPath + ": " + err.toString());
if(!response.headersSent) {
state.sendResponse(500,{"Content-Type": "text/plain"},"Write error");
}
});
stream.on("finish", function() {
if(!response.headersSent) {
state.sendResponse(204,{"Content-Type": "text/plain"},"");
}
});
request.on("error", function(err) {
$tw.utils.error("Error reading request for " + fullPath + ": " + err.toString());
stream.destroy();
});
request.pipe(stream);
});
};

View file

@ -0,0 +1,10 @@
title: $:/changenotes/5.4.0/#9075
description: Add PUT endpoint for file uploads
release: 5.4.0
tags: $:/tags/ChangeNote
change-type: enhancement
change-category: nodejs
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/9075
github-contributors: linonetwo
A new WebServer API endpoint PUT `/files/<pathname>` that supports streaming uploads for large files.

View file

@ -0,0 +1,35 @@
created: 20250603144839000
modified: 20250603144839000
tags: [[WebServer API]]
title: WebServer API: Put File
type: text/vnd.tiddlywiki
<<.from-version "5.4.0">> Upload or update a [[static file|Using the integrated static file server]].
```
PUT /files/<pathname>
```
The body should contain the raw file content (binary or text).
Parameters:
* ''pathname'' - URI encoded path to the file
Headers:
* ''x-requested-with'' - must be set to `TiddlyWiki` in order for the request to succeed, unless [[WebServer Parameter: csrf-disable]] is set to `yes`
* ''content-type'' - should be set to the appropriate MIME type for the file being uploaded
Response:
* 204 No Content
*> `Content-Type: text/plain`
* 403 Forbidden - if the file path attempts to access directories outside the files folder
* 500 Internal Server Error - if there was an error creating directories or writing the file
Notes:
* The file will be created in the wiki's `files` directory
* Parent directories will be created automatically if path is like `files/subdir/file.png`
* Files are stored exactly as uploaded without any processing or validation, no tiddler will be created automatically