在hapijs 17.0上传个人资料照片

时间:2017-12-25 17:54:43

标签: ajax file-upload multipartform-data hapijs content-length

我正在使用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
                };
            });
        }
    }

上面的代码在cannot read property 'content-length' of undefined

行给出了错误form.parse(request.payload, function (err, fields, files) {});

如果我做错了,请告诉我。如果我使用我用php编写的anohter url替换ajax请求中的url,那么它可以正常工作。这意味着我的hapijs / nodejs代码出了问题。

1 个答案:

答案 0 :(得分:0)

关于如何在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