使用 multer 和 nodejs 将图像上传到 google 云存储时出错
Uploading images to google cloud storage with multer and nodejs getting error
== 9 月 9 日更新了问题 ===
尝试直接使用 Multer 而不像以前那样使用中间件并使用 Postman 上传图像。
来自 Nodejs,请求 return
files: [Object: null prototype] {
imagebackup: [ [Object] ],
imagebanner: [ [Object] ]
},
然而,当我安慰req.file
它显示“未定义”
新建文件-routers.js如下:
const express = require('express');
const multer = require('multer');
const router = express.Router();
const upload = multer({
storage: multer.MemoryStorage,
}).fields([{name: "imagebackup"}, {name: "imagebanner"}]);
router.post('/file', (req, res)=>{
upload(req, res, (err) => {
console.log(req) // return Files [object null]
console.log(req.file) // return "undefined"
if(err) throw err;
})
});
** 奇怪的是,通过使用 upload.single(),一切正常。 **
==
==
=====这里是旧代码,无法解决=====
它return一个错误
MulterError: Unexpected field
at wrappedFileFilter (C:\Users\carchaw\Documents\pfx_template_generator_api\node_modules\multer\index.js:40:19)
at Busboy.<anonymous> (C:\Users\carchaw\Documents\pfx_template_generator_api\node_modules\multer\lib\make-middleware.js:114:7)
at Busboy.emit (node:events:379:20)
在提交表单时,我需要从不同的输入字段上传 2 张图片,在 GCS 上创建新的前缀,并将要发送的图片名称和其他详细信息存储在 request.body。
在前端部分,我使用 Fetch 如下:
const getFormContianer = document.getElementById("get_form")
async function handleForm(e) {
e.preventDefault();
let dataForm = new FormData(e.target)
await fetch(file_api, {
method: 'POST',
body: dataForm
}).then((res)=>{
return res.json();
}).then((data)=>{
console.log('api err: '+data);
}).catch((err) =>{
console.log('api err: '+ err)
})
}
getFormContianer.addEventListener('submit', handleForm)
index.html
<form id="get_form">
<label for="video_url">video_url</label>
<input name="video_url" type="text" id="video_url" value=""><br>
<label for="image_backup">image_backup</label>
<input name="image_backup" type="file" id="image_backup" value=""><br>
<label for="image_banner">image_banner</label>
<input name="image_banner" type="file" id="image_banner" value=""><br>
</form>
<input type="submit" id="handle_submit">
节点
multer 中间件
const util = require("util");
const multer = require("multer");
let processFile = multer({
storage: multer.memoryStorage()
}).fields([{ name: "image_backup" }, { name: "image_banner" }])
let processFileMiddleware = util.promisify(processFile);
module.exports = processFileMiddleware;
处理上传
const handleUploadImages = async (req, res) =>{
try {
await processFile(req, res);
if (!req.file) {
return res.status(400).send({ message: "Please upload a file!" });
}
// Create a new blob in the bucket and upload the file data.
const blob = bucket.file(newFolderPath + req.file.originalname);
const blobStream = blob.createWriteStream({
resumable: false,
});
blobStream.on("error", (err) => {
res.status(500).send({ message: err.message });
});
blobStream.on("finish", async (data) => {
// Create URL for directly file access via HTTP.
const publicUrl = format(
`https://storage.googleapis.com/${bucket.name}/${newFolderPath}/${blob.name}`
);
try {
// Make the file public
await bucket.file(newFolderPath + req.file.originalname).makePublic();
} catch {
return res.status(500).send({
message:
`Uploaded the file successfully: ${newFolderPath + req.file.originalname}, but public access is denied!`,
url: publicUrl,
});
}
res.status(200).send({
message: "Uploaded the file successfully: " + newFolderPath + req.file.originalname,
url: publicUrl,
});
});
blobStream.end(req.file.buffer);
} catch (err) {
res.status(500).send({
message: `Could not upload the file: ${req.file.originalname}. ${err}`,
});
}
}
我确实使用了 express json 并在 index.js
上进行了 urlencoded
const express = require('express');
const cors = require('cors');
const config = require('./config')
const app = express()
const templates = require('./routes/templates-routes');
const files = require('./routes/files-routes');
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'))
app.use('/api', templates.routes);
app.use('/create', files.routes);
app.listen(config.port, () => {
console.log(`Example app listening at http://localhost:${config.port}`)
})
希望能得到一些建议,谢谢!
body: dataForm
声明在哪里?当您尝试上传字段中未提及的字段时出现该错误:
fields([{ name: "image_backup" }, { name: "image_banner" }])
确保您的多部分表单仅包含这 2 个用于上传文件的字段。
我建议你查看这个 post,他们在其中讨论 。
为了解决这个问题,他们基本上格式化了需要上传的文件。
formData.append("type_of_the_file", uploadfile);
经过几天的努力,终于解决了这个问题。
对于前端 POST rest API,通过附加文件本身和名称来传递文件。
function handleForm(e) {
e.preventDefault();
let dataForm = new FormData(e.target)
dataForm.append("image_backup", document.getElementById("image_backup").files[0]);
dataForm.append("image_banner", document.getElementById("image_banner").files[0]);
dataForm.append("image_banner_name", document.getElementById("image_banner").value.replace(/^.*[\\/]/, ''));
dataForm.append("image_backup_name", document.getElementById("image_backup").value.replace(/^.*[\\/]/, ''));
await fetch(file_api, {
method: 'POST',
body: dataForm
}).then((res)=>{
return res.json();
}).then((data)=>{
console.log('api data: '+ data);
}).catch((err) =>{
console.log('api err: '+ err)
})
}
在 Node.js 上
const multer = require('multer');
const upload = multer({
storage: multer.MemoryStorage,
}).fields([{name: "image_backup"}, {name: "image_banner"}]);
const startCreatefiles = async(req, res, next) =>{
upload(req, res, (err) => {
console.log(req.body);
console.log(req.files);
})
}
然后成功获取到文本表单数据和文件本身。
== 9 月 9 日更新了问题 ===
尝试直接使用 Multer 而不像以前那样使用中间件并使用 Postman 上传图像。
来自 Nodejs,请求 return
files: [Object: null prototype] {
imagebackup: [ [Object] ],
imagebanner: [ [Object] ]
},
然而,当我安慰req.file 它显示“未定义”
新建文件-routers.js如下:
const express = require('express');
const multer = require('multer');
const router = express.Router();
const upload = multer({
storage: multer.MemoryStorage,
}).fields([{name: "imagebackup"}, {name: "imagebanner"}]);
router.post('/file', (req, res)=>{
upload(req, res, (err) => {
console.log(req) // return Files [object null]
console.log(req.file) // return "undefined"
if(err) throw err;
})
});
** 奇怪的是,通过使用 upload.single(),一切正常。 **
==
== =====这里是旧代码,无法解决===== 它return一个错误
MulterError: Unexpected field
at wrappedFileFilter (C:\Users\carchaw\Documents\pfx_template_generator_api\node_modules\multer\index.js:40:19)
at Busboy.<anonymous> (C:\Users\carchaw\Documents\pfx_template_generator_api\node_modules\multer\lib\make-middleware.js:114:7)
at Busboy.emit (node:events:379:20)
在提交表单时,我需要从不同的输入字段上传 2 张图片,在 GCS 上创建新的前缀,并将要发送的图片名称和其他详细信息存储在 request.body。
在前端部分,我使用 Fetch 如下:
const getFormContianer = document.getElementById("get_form")
async function handleForm(e) {
e.preventDefault();
let dataForm = new FormData(e.target)
await fetch(file_api, {
method: 'POST',
body: dataForm
}).then((res)=>{
return res.json();
}).then((data)=>{
console.log('api err: '+data);
}).catch((err) =>{
console.log('api err: '+ err)
})
}
getFormContianer.addEventListener('submit', handleForm)
index.html
<form id="get_form">
<label for="video_url">video_url</label>
<input name="video_url" type="text" id="video_url" value=""><br>
<label for="image_backup">image_backup</label>
<input name="image_backup" type="file" id="image_backup" value=""><br>
<label for="image_banner">image_banner</label>
<input name="image_banner" type="file" id="image_banner" value=""><br>
</form>
<input type="submit" id="handle_submit">
节点
multer 中间件
const util = require("util");
const multer = require("multer");
let processFile = multer({
storage: multer.memoryStorage()
}).fields([{ name: "image_backup" }, { name: "image_banner" }])
let processFileMiddleware = util.promisify(processFile);
module.exports = processFileMiddleware;
处理上传
const handleUploadImages = async (req, res) =>{
try {
await processFile(req, res);
if (!req.file) {
return res.status(400).send({ message: "Please upload a file!" });
}
// Create a new blob in the bucket and upload the file data.
const blob = bucket.file(newFolderPath + req.file.originalname);
const blobStream = blob.createWriteStream({
resumable: false,
});
blobStream.on("error", (err) => {
res.status(500).send({ message: err.message });
});
blobStream.on("finish", async (data) => {
// Create URL for directly file access via HTTP.
const publicUrl = format(
`https://storage.googleapis.com/${bucket.name}/${newFolderPath}/${blob.name}`
);
try {
// Make the file public
await bucket.file(newFolderPath + req.file.originalname).makePublic();
} catch {
return res.status(500).send({
message:
`Uploaded the file successfully: ${newFolderPath + req.file.originalname}, but public access is denied!`,
url: publicUrl,
});
}
res.status(200).send({
message: "Uploaded the file successfully: " + newFolderPath + req.file.originalname,
url: publicUrl,
});
});
blobStream.end(req.file.buffer);
} catch (err) {
res.status(500).send({
message: `Could not upload the file: ${req.file.originalname}. ${err}`,
});
}
}
我确实使用了 express json 并在 index.js
上进行了 urlencodedconst express = require('express');
const cors = require('cors');
const config = require('./config')
const app = express()
const templates = require('./routes/templates-routes');
const files = require('./routes/files-routes');
// Middleware
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'))
app.use('/api', templates.routes);
app.use('/create', files.routes);
app.listen(config.port, () => {
console.log(`Example app listening at http://localhost:${config.port}`)
})
希望能得到一些建议,谢谢!
body: dataForm
声明在哪里?当您尝试上传字段中未提及的字段时出现该错误:
fields([{ name: "image_backup" }, { name: "image_banner" }])
确保您的多部分表单仅包含这 2 个用于上传文件的字段。
我建议你查看这个 post,他们在其中讨论
为了解决这个问题,他们基本上格式化了需要上传的文件。
formData.append("type_of_the_file", uploadfile);
经过几天的努力,终于解决了这个问题。
对于前端 POST rest API,通过附加文件本身和名称来传递文件。
function handleForm(e) {
e.preventDefault();
let dataForm = new FormData(e.target)
dataForm.append("image_backup", document.getElementById("image_backup").files[0]);
dataForm.append("image_banner", document.getElementById("image_banner").files[0]);
dataForm.append("image_banner_name", document.getElementById("image_banner").value.replace(/^.*[\\/]/, ''));
dataForm.append("image_backup_name", document.getElementById("image_backup").value.replace(/^.*[\\/]/, ''));
await fetch(file_api, {
method: 'POST',
body: dataForm
}).then((res)=>{
return res.json();
}).then((data)=>{
console.log('api data: '+ data);
}).catch((err) =>{
console.log('api err: '+ err)
})
}
在 Node.js 上
const multer = require('multer');
const upload = multer({
storage: multer.MemoryStorage,
}).fields([{name: "image_backup"}, {name: "image_banner"}]);
const startCreatefiles = async(req, res, next) =>{
upload(req, res, (err) => {
console.log(req.body);
console.log(req.files);
})
}
然后成功获取到文本表单数据和文件本身。