在 hapijs 17.0 中上传个人资料图片
uploading profile pic in hapijs 17.0
我使用的是 hapijs 版本 17.0.1。我正在尝试在 hapijs 路由上使用 ajax 请求上传图像。这是我的 AJAX 上传个人资料图片的代码:
var image_file_input = document.getElementById("user_profile_upload");
image_file_input.onchange = function () {
if(this.files != undefined)
{
if(this.files[0] != undefined)
{
var formData = tests.formdata ? new FormData() : null;
if (tests.formdata)
{
//alert(file)
formData.append('image_file', this.files[0]);
formData.append('userId', user_id);
formData.append('memberId', member_id);
}
$.ajax({
url: "/v1/User/uploadUserPic",
data: formData,
type: "POST",
dataType: "json",
contentType: false,
processData: false,
contentType: "multipart/form-data",
success: function(data){
console.log(data);
var errMsg = null;
var resData = null;
if(data.statusCode == 200)
{
resData = data.result;
}
else
{
alert(data.message)
}
},
error: function(error){
alert(error);
}
});
}
}
}
这是我的 Hapijs 路由代码:
var uploadUserPic = {
method: 'POST',
path: '/v1/Module/uploadUserPic',
config: {
description: 'Update Image For User',
tags: ['api', 'User'],
auth: 'session',
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
userId : Joi.string().regex(/^[a-f\d]{24}$/i).required(),
memberId: Joi.string().required(),
image_file: Joi.object().required(),
},
failAction: FailCallBack
}
},
handler: function (request, reply) {
var resultData = null;
var error = null;
return new Promise(function (resolve) {
var multiparty = require('multiparty');
var fs = require('fs');
var form = new multiparty.Form();
form.parse(request.payload, function (err, fields, files) {
if(err)
{
error = err;
resolve();
}
else
{
var mkdirp = require('mkdirp');
var img_dir = "./files/users/";
mkdirp(img_dir, function (err) {
if (err)
{
error = err;
console.error(err);
resolve();
}
else
{
var oldpath = files.image_file.path;
var newpath = "./files/users/"+requestPayload.userId+".png";
fs.rename(oldpath, newpath, function (err) {
if(err)
{
error = err;
}
resolve();
});
}
});
}
});
}).then(function (err, result) {
if(err) return sendError(err);
if(error) return sendError(error)
return {
"statusCode": 200,
"success": true
};
});
}
}
上面的代码在行 form.parse(request.payload, function (err, fields, files) {});
上给出了以下错误 cannot read property 'content-length' of undefined
如果我做错了什么,请告诉我。如果我将 ajax 请求中的 url 替换为我在 php 中编写的另一个 url,那么它将完美运行。这意味着我的 hapijs/nodejs 代码有问题。
post Hapi.js 中有一篇很好的关于如何处理文件上传的文章(写于第 16 版)https://scotch.io/bar-talk/handling-file-uploads-with-hapi-js
由于您使用的是 payload.parse = true
,我看不出您必须使用 multiparty
的具体原因。我有以下工作代码,可以将从客户端上传的文件(任何类型)保存到服务器上的上传目录中(请不要直接在生产中使用,因为没有完成卫生)
{
path: '/upload',
method: 'POST',
config: {
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
files: Joi.array().single()
}
}
},
handler: function(request) {
const p = request.payload, files = p.files
if(files) {
console.log(`${files.length} files`)
files.forEach(async file => {
const filename= file.hapi.filename
console.log(`Saving ${filename} to ./uploads`)
const out = fs.createWriteStream(`./uploads/${filename}`)
await file.pipe(out)
})
}
return {result: 'ok'}
}
}
可以使用以下curl命令进行测试
curl http://localhost:8080/upload -F 'files=@/path/to/a/note.txt' -F 'files=@/path/to/test.png' -vvv
您的代码存在一些问题。首先在您的 $.ajax
调用中,您指定了 contentType
两次,虽然这不是语法错误,但这样编码是粗心的。其次,您的 .then() 块中的函数签名不正确。您正在混合 Promise 和回调的想法。我认为不会触发以下行
if(err) return sendError(err);
最后一件小事,你说你使用的是 Hapi 17 但基于处理函数的签名
handler: function (request, reply) {
...
看来您还没有完全接受 Hapi17,因为新签名是
handler: function (request, h) {
这不仅仅是将 reply
重命名为 h
。
我使用的是 hapijs 版本 17.0.1。我正在尝试在 hapijs 路由上使用 ajax 请求上传图像。这是我的 AJAX 上传个人资料图片的代码:
var image_file_input = document.getElementById("user_profile_upload");
image_file_input.onchange = function () {
if(this.files != undefined)
{
if(this.files[0] != undefined)
{
var formData = tests.formdata ? new FormData() : null;
if (tests.formdata)
{
//alert(file)
formData.append('image_file', this.files[0]);
formData.append('userId', user_id);
formData.append('memberId', member_id);
}
$.ajax({
url: "/v1/User/uploadUserPic",
data: formData,
type: "POST",
dataType: "json",
contentType: false,
processData: false,
contentType: "multipart/form-data",
success: function(data){
console.log(data);
var errMsg = null;
var resData = null;
if(data.statusCode == 200)
{
resData = data.result;
}
else
{
alert(data.message)
}
},
error: function(error){
alert(error);
}
});
}
}
}
这是我的 Hapijs 路由代码:
var uploadUserPic = {
method: 'POST',
path: '/v1/Module/uploadUserPic',
config: {
description: 'Update Image For User',
tags: ['api', 'User'],
auth: 'session',
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
userId : Joi.string().regex(/^[a-f\d]{24}$/i).required(),
memberId: Joi.string().required(),
image_file: Joi.object().required(),
},
failAction: FailCallBack
}
},
handler: function (request, reply) {
var resultData = null;
var error = null;
return new Promise(function (resolve) {
var multiparty = require('multiparty');
var fs = require('fs');
var form = new multiparty.Form();
form.parse(request.payload, function (err, fields, files) {
if(err)
{
error = err;
resolve();
}
else
{
var mkdirp = require('mkdirp');
var img_dir = "./files/users/";
mkdirp(img_dir, function (err) {
if (err)
{
error = err;
console.error(err);
resolve();
}
else
{
var oldpath = files.image_file.path;
var newpath = "./files/users/"+requestPayload.userId+".png";
fs.rename(oldpath, newpath, function (err) {
if(err)
{
error = err;
}
resolve();
});
}
});
}
});
}).then(function (err, result) {
if(err) return sendError(err);
if(error) return sendError(error)
return {
"statusCode": 200,
"success": true
};
});
}
}
上面的代码在行 form.parse(request.payload, function (err, fields, files) {});
cannot read property 'content-length' of undefined
如果我做错了什么,请告诉我。如果我将 ajax 请求中的 url 替换为我在 php 中编写的另一个 url,那么它将完美运行。这意味着我的 hapijs/nodejs 代码有问题。
post Hapi.js 中有一篇很好的关于如何处理文件上传的文章(写于第 16 版)https://scotch.io/bar-talk/handling-file-uploads-with-hapi-js
由于您使用的是 payload.parse = true
,我看不出您必须使用 multiparty
的具体原因。我有以下工作代码,可以将从客户端上传的文件(任何类型)保存到服务器上的上传目录中(请不要直接在生产中使用,因为没有完成卫生)
{
path: '/upload',
method: 'POST',
config: {
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
files: Joi.array().single()
}
}
},
handler: function(request) {
const p = request.payload, files = p.files
if(files) {
console.log(`${files.length} files`)
files.forEach(async file => {
const filename= file.hapi.filename
console.log(`Saving ${filename} to ./uploads`)
const out = fs.createWriteStream(`./uploads/${filename}`)
await file.pipe(out)
})
}
return {result: 'ok'}
}
}
可以使用以下curl命令进行测试
curl http://localhost:8080/upload -F 'files=@/path/to/a/note.txt' -F 'files=@/path/to/test.png' -vvv
您的代码存在一些问题。首先在您的 $.ajax
调用中,您指定了 contentType
两次,虽然这不是语法错误,但这样编码是粗心的。其次,您的 .then() 块中的函数签名不正确。您正在混合 Promise 和回调的想法。我认为不会触发以下行
if(err) return sendError(err);
最后一件小事,你说你使用的是 Hapi 17 但基于处理函数的签名
handler: function (request, reply) {
...
看来您还没有完全接受 Hapi17,因为新签名是
handler: function (request, h) {
这不仅仅是将 reply
重命名为 h
。