【问题标题】:uploading profile pic in hapijs 17.0在 hapijs 17.0 中上传个人资料图片
【发布时间】:2018-06-06 20:12:06
【问题描述】:

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

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

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • sendError 只是格式化我的错误。其次,我知道它的 h 而不是 reply。但我从 hapi 14 升级到了 17,所以我不得不在整个项目中更改它。 h 对我来说也有点尴尬。所以我认为reply 只是一个变量表示,并用reply 变量调用h 的属性/函数。顺便谢谢你的帮助伙伴。我会检查您的解决方案并回复您。
    • 它就像一个魅力伴侣。谢谢你的帮助。很高兴接受您的回答。
    • 完全没问题。很高兴为您提供帮助:D
    猜你喜欢
    • 2020-01-10
    • 2014-04-14
    • 2015-05-22
    • 1970-01-01
    • 2014-10-05
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多