mirror of
https://github.com/Molunerfinn/PicGo.git
synced 2026-09-20 03:16:37 +00:00
✨ Feature(server): add support for form upload in PicGo Server (#1327)
ISSUES CLOSED: #428
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
"lowdb": "^1.0.0",
|
||||
"marked": "^7.0.4",
|
||||
"mitt": "^3.0.0",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"picgo": "^1.5.8",
|
||||
"qrcode.vue": "^3.3.3",
|
||||
"shell-path": "2.1.0",
|
||||
@@ -54,6 +55,7 @@
|
||||
"@types/inquirer": "^6.5.0",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/lowdb": "^1.0.9",
|
||||
"@types/multer": "^1.4.12",
|
||||
"@types/node": "^16.10.2",
|
||||
"@types/request-promise-native": "^1.0.17",
|
||||
"@types/semver": "^7.3.8",
|
||||
|
||||
@@ -4,9 +4,64 @@ import {
|
||||
handleResponse,
|
||||
ensureHTTPLink
|
||||
} from './utils'
|
||||
import { dbPathDir } from 'apis/core/datastore/dbChecker'
|
||||
import picgo from '@core/picgo'
|
||||
import logger from '@core/picgo/logger'
|
||||
import axios from 'axios'
|
||||
import multer from 'multer'
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
|
||||
// 扩展原生 IncomingMessage,添加 multer 字段
|
||||
declare module 'http' {
|
||||
interface IncomingMessage {
|
||||
files?: {
|
||||
path: string;
|
||||
originalname: string;
|
||||
mimetype: string;
|
||||
size: number;
|
||||
[key: string]: any;
|
||||
}[];
|
||||
body?: any;
|
||||
}
|
||||
}
|
||||
|
||||
// Multer 中间件适配器类型
|
||||
export type MulterMiddleware = (
|
||||
req: http.IncomingMessage,
|
||||
res: http.ServerResponse,
|
||||
callback: (error?: any) => void
|
||||
) => void;
|
||||
|
||||
// 扩展 multer 函数的返回类型
|
||||
declare module 'multer' {
|
||||
interface Multer {
|
||||
array(fieldname: string, maxCount?: number): MulterMiddleware;
|
||||
single(fieldname: string): MulterMiddleware;
|
||||
fields(fields: { name: string; maxCount?: number }[]): MulterMiddleware;
|
||||
none(): MulterMiddleware;
|
||||
}
|
||||
}
|
||||
|
||||
const STORE_PATH = dbPathDir()
|
||||
const formImagesPath = path.join(STORE_PATH, 'picgo-form-images')
|
||||
if (!fs.existsSync(formImagesPath)) {
|
||||
fs.mkdirSync(formImagesPath, { recursive: true })
|
||||
}
|
||||
|
||||
// 使用 multer 处理表单文件
|
||||
const storage = multer.diskStorage({
|
||||
destination: function (req, file, cb) {
|
||||
cb(null, formImagesPath)
|
||||
},
|
||||
filename: function (req, file, cb) {
|
||||
cb(null, Date.now() + path.extname(file.originalname))
|
||||
}
|
||||
})
|
||||
|
||||
const upload = multer({
|
||||
storage
|
||||
})
|
||||
|
||||
class Server {
|
||||
private httpServer: http.Server
|
||||
@@ -56,6 +111,51 @@ class Server {
|
||||
success: false
|
||||
}
|
||||
})
|
||||
} else if (request.headers['content-type'] && request.headers['content-type'].includes('multipart/form-data')) {
|
||||
logger.info('[PicGo Server] handling file upload')
|
||||
upload.array('files')(request, response, async (err) => {
|
||||
if (err) {
|
||||
logger.error('[PicGo Server] file upload error', err)
|
||||
return handleResponse({
|
||||
response,
|
||||
body: {
|
||||
success: false,
|
||||
message: 'File upload failed'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const files = (request).files
|
||||
if (!files || files.length === 0) {
|
||||
return handleResponse({
|
||||
response,
|
||||
body: {
|
||||
success: false,
|
||||
message: 'No files were uploaded'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const filePaths = files.map((file) => file.path)
|
||||
logger.info('[PicGo Server] files uploaded: ' + filePaths.join(', '))
|
||||
|
||||
const handler = routers.getHandler(request.url!)
|
||||
handler!({
|
||||
list: filePaths,
|
||||
response
|
||||
})
|
||||
} catch (err: any) {
|
||||
logger.error('[PicGo Server] process upload files error', err)
|
||||
handleResponse({
|
||||
response,
|
||||
body: {
|
||||
success: false,
|
||||
message: 'Failed to process uploaded files'
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
let body: string = ''
|
||||
let postObj: IObj
|
||||
|
||||
@@ -2906,6 +2906,13 @@
|
||||
resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
|
||||
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
||||
|
||||
"@types/multer@^1.4.12":
|
||||
version "1.4.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/multer/-/multer-1.4.12.tgz#da67bd0c809f3a63fe097c458c0d4af1fea50ab7"
|
||||
integrity sha512-pQ2hoqvXiJt2FP9WQVLPRO+AmiIm/ZYkavPlIQnx282u4ZrVdztx0pkh3jjpQt0Kz+YI0YhSG264y08UJKoUQg==
|
||||
dependencies:
|
||||
"@types/express" "*"
|
||||
|
||||
"@types/node@*", "@types/node@^14.6.2", "@types/node@^16.10.2":
|
||||
version "16.11.18"
|
||||
resolved "https://registry.npmjs.org/@types/node/-/node-16.11.18.tgz#39ed7c52943b0cee6d7299b717707bd51b1f90b9"
|
||||
@@ -3950,6 +3957,11 @@ app-builder-lib@23.3.3:
|
||||
tar "^6.1.11"
|
||||
temp-file "^3.4.0"
|
||||
|
||||
append-field@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
|
||||
integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==
|
||||
|
||||
arch@^2.1.1:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
|
||||
@@ -4472,6 +4484,13 @@ builtins@^5.0.1:
|
||||
dependencies:
|
||||
semver "^7.0.0"
|
||||
|
||||
busboy@^1.0.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
|
||||
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
|
||||
dependencies:
|
||||
streamsearch "^1.1.0"
|
||||
|
||||
bytes@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||
@@ -5019,7 +5038,7 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||
|
||||
concat-stream@^1.6.2:
|
||||
concat-stream@^1.5.2, concat-stream@^1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
|
||||
@@ -9344,6 +9363,19 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1:
|
||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
multer@^1.4.5-lts.1:
|
||||
version "1.4.5-lts.1"
|
||||
resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac"
|
||||
integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==
|
||||
dependencies:
|
||||
append-field "^1.0.0"
|
||||
busboy "^1.0.0"
|
||||
concat-stream "^1.5.2"
|
||||
mkdirp "^0.5.4"
|
||||
object-assign "^4.1.1"
|
||||
type-is "^1.6.4"
|
||||
xtend "^4.0.0"
|
||||
|
||||
multicast-dns@^7.2.5:
|
||||
version "7.2.5"
|
||||
resolved "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced"
|
||||
@@ -9539,7 +9571,7 @@ number-is-nan@^1.0.0:
|
||||
resolved "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||
|
||||
object-assign@^4.0.1, object-assign@^4.1.0:
|
||||
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
@@ -11580,6 +11612,11 @@ stream-browserify@3.0.0:
|
||||
inherits "~2.0.4"
|
||||
readable-stream "^3.5.0"
|
||||
|
||||
streamsearch@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
|
||||
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||
|
||||
strict-uri-encode@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713"
|
||||
@@ -12210,7 +12247,7 @@ type-fest@^0.8.1:
|
||||
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
||||
type-is@~1.6.18:
|
||||
type-is@^1.6.4, type-is@~1.6.18:
|
||||
version "1.6.18"
|
||||
resolved "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||
|
||||
Reference in New Issue
Block a user