Docker部署的Next.js中Zip文件上传无存储问题求助
问题描述
在Docker容器中部署的Next.js实例里,需求是通过UI上传Zip文件并存储到容器内的/tmp/compressed/${文件名}路径。调用上传接口后返回200 OK,但目标路径下并未出现存储的文件。已尝试使用multer、formidable以及基于fs的API实现该功能,均未成功。
UI代码(/pages/uploadData.js)
import { useState } from 'react'; import axios from 'axios'; import { useRouter } from 'next/router'; require('dotenv').config(); export default function UploadData() { const [selectedFile, setSelectedFile] = useState(null); const router = useRouter(); const handleBack = () => { router.push('/'); }; const handleFileSelect = (event) => { setSelectedFile(event.target.files[0]); }; const handleUpload = async () => { if (!selectedFile) { alert('Please select a file first.'); return; } const formData = new FormData(); formData.append('file', selectedFile); try { await axios.post('/api/uploadFolder', formData); alert('File uploaded successfully'); } catch (error) { console.error('Error uploading file UPLOAD DATA:', error); alert('An error occurred while uploading the file.'); } }; return ( <div> <h1>Upload Zip File</h1> <div> <button onClick={handleBack}>Back</button> </div> <input type="file" onChange={handleFileSelect} /> <button onClick={handleUpload} disabled={!selectedFile}>Upload</button> </div> ); }
原错误接口代码(/pages/api/uploadFolder.js)
import multer from "multer"; const storage = multer.diskStorage({ destination: "/tmp/compressed", filename: (req, file, cb) => { cb(null, file.originalname); }, }); const upload = multer({ storage }); export default async function handler(req, res) { if (req.method === "POST") { const uploadedFile = await upload.single("file"); if (uploadedFile) { res.status(200).json({ message: "Archivo cargado correctamente" }); } else { res.status(400).json({ error: "Error al cargar el archivo" }); } } else { res.status(405).json({ error: "Método no permitido" }); } }
问题分析与修复方案
核心问题
- multer调用逻辑错误:
upload.single('file')是Express风格的中间件函数,并非异步Promise,直接await不会触发文件上传流程,函数直接返回undefined,导致接口提前返回200但文件未处理。 - 目标目录可能不存在:multer不会自动创建
destination指定的目录,若/tmp/compressed不存在,上传会静默失败。
修复后的接口代码
import multer from "multer"; import fs from "fs"; import path from "path"; // 确保目标目录存在,不存在则递归创建 const uploadDir = "/tmp/compressed"; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } const storage = multer.diskStorage({ destination: uploadDir, filename: (req, file, cb) => { cb(null, file.originalname); }, }); const upload = multer({ storage, limits: { fileSize: 10 * 1024 * 1024 } // 可根据需求调整文件大小限制,此处为10MB }); // 将multer中间件包装为Promise,适配Next.js API路由 const uploadSingle = (req, res) => { return new Promise((resolve, reject) => { upload.single("file")(req, res, (err) => { if (err) reject(err); resolve(req.file); }); }); }; export default async function handler(req, res) { if (req.method === "POST") { try { const uploadedFile = await uploadSingle(req, res); res.status(200).json({ message: "Archivo cargado correctamente", file: uploadedFile }); } catch (error) { console.error("上传错误:", error); res.status(400).json({ error: "Error al cargar el archivo", details: error.message }); } } else { res.status(405).json({ error: "Método no permitido" }); } }
额外检查项
- Docker目录权限:确认容器内
/tmp/compressed目录的读写权限,Next.js进程用户(通常是node)需具备写入权限,可在Dockerfile中添加:RUN mkdir -p /tmp/compressed && chown -R node:node /tmp/compressed
内容的提问来源于stack exchange,提问作者Daniel Riaño
相关产品推荐
相关产品推荐

