Dev #6

Merged
bytegrip merged 3 commits from dev into main 2025-06-18 12:50:18 +00:00
6 changed files with 149 additions and 43 deletions

2
.gitignore vendored
View File

@@ -4,6 +4,8 @@ obj/
riderModule.iml
/_ReSharper.Caches/
.idea
uploads
uploads/
.vs
.vs/
.vscode/

15
Dockerfile Normal file
View File

@@ -0,0 +1,15 @@
FROM node:18-alpine
WORKDIR /app
COPY scripts/package.json ./
RUN npm install
COPY scripts/upload-server.js ./
RUN mkdir -p uploads
EXPOSE 3000
CMD ["npm", "start"]

View File

@@ -94,41 +94,26 @@ services:
- webapi
- webui
- seq
- upload-server
networks:
- app-network
zipline:
image: ghcr.io/diced/zipline:latest
expose:
- "3000"
upload-server:
build: .
ports:
- "3000:3000"
environment:
- CORE_RETURN_HTTPS=true
- CORE_SECRET=${ZIPLINE_SECRET}
- CORE_HOST=0.0.0.0
- CORE_PORT=3000
- CORE_DATABASE_URL=file:./zipline.db
- CORE_LOGGER=true
- URLS_ROUTE=${ZIPLINE_ROUTE}
- URLS_LENGTH=6
- UPLOADER_DEFAULT_FORMAT=RANDOM
- UPLOADER_DISABLED_EXTENSIONS=
- UPLOADER_FORMAT_DATE=%Y-%m-%d_%H-%M-%S
- FEATURES_INVITES=false
- FEATURES_REGISTRATION=false
- FEATURES_HEADLESS=true
- FEATURES_USER_REGISTRATION=false
- FEATURES_OAUTH_REGISTRATION=false
- FEATURES_ANONYMOUS_UPLOAD=true
- WEBSITE_TITLE=File Upload
- WEBSITE_EXTERNAL_LINKS=${ZIPLINE_URL}
- BASE_URL=https://impr.ink
- HASH_FILENAME=true
- UPLOAD_DIR=/app/uploads
volumes:
- zipline_data:/zipline/uploads
- zipline_public:/zipline/public
- zipline_db:/zipline
restart: unless-stopped
- ./uploads:/app/uploads
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
upload_data:

View File

@@ -21,8 +21,8 @@ http {
server seq:80;
}
upstream zipline {
server zipline:3000;
upstream upload-server {
server upload-server:3000;
}
server {
@@ -85,23 +85,38 @@ http {
rewrite ^/seq/(.*)$ /$1 break;
}
location /res {
proxy_pass http://zipline;
location /upload {
proxy_pass http://upload-server/upload;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /res;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
rewrite ^/res/(.*)$ /$1 break;
rewrite ^/res$ / break;
client_max_body_size 1G;
}
location ~ ^/files/(.+)$ {
proxy_pass http://upload-server/files/$1;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
client_max_body_size 1G;
}
location / {

13
scripts/package.json Normal file
View File

@@ -0,0 +1,13 @@
{
"name": "upload-server",
"version": "1.0.0",
"main": "upload-server.js",
"scripts": {
"start": "node upload-server.js"
},
"dependencies": {
"express": "^4.18.2",
"multer": "^1.4.5-lts.1",
"uuid": "^9.0.0"
}
}

76
scripts/upload-server.js Normal file
View File

@@ -0,0 +1,76 @@
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');
const { v4: uuidv4 } = require('uuid');
const app = express();
const PORT = process.env.PORT || 3000;
const BASE_URL = process.env.BASE_URL || 'http://localhost:3000';
const UPLOAD_DIR = process.env.UPLOAD_DIR || './uploads';
const HASH_FILENAME = process.env.HASH_FILENAME === 'true';
if (!fs.existsSync(UPLOAD_DIR)) {
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
}
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, UPLOAD_DIR);
},
filename: (req, file, cb) => {
if (HASH_FILENAME) {
const ext = path.extname(file.originalname);
const filename = uuidv4() + ext;
cb(null, filename);
} else {
cb(null, file.originalname);
}
}
});
const upload = multer({ storage });
app.post('/upload', upload.single('file'), (req, res) => {
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded' });
}
const fileUrl = `${BASE_URL}/files/${req.file.filename}`;
res.json({ url: fileUrl });
});
app.put('/files/:path(*)', upload.single('file'), (req, res) => {
const filePath = req.params.path;
if (!req.file) {
return res.status(400).json({ error: 'No file uploaded' });
}
const oldPath = req.file.path;
const newPath = path.join(UPLOAD_DIR, filePath);
const dir = path.dirname(newPath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.renameSync(oldPath, newPath);
const fileUrl = `${BASE_URL}/files/${filePath}`;
res.json({ url: fileUrl });
});
app.get('/files/:path(*)', (req, res) => {
const filePath = path.join(UPLOAD_DIR, req.params.path);
if (!fs.existsSync(filePath)) {
return res.status(404).json({ error: 'File not found' });
}
res.sendFile(path.resolve(filePath));
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});