如何使用JavaScript中的http.post将图像发送到服务器并在MongoDB中存储base64?

16

我在客户端使用http请求将图片存储到mongodb服务器时遇到了麻烦。非常感激您的帮助,我需要一个简单的示例,说明如何将图像文件作为数据添加到http post请求中,例如XMLhttprequest。假设我知道服务器方法的URL,图像的来源在__内定义。

imgsrc
一个文件的名称被存储在中。
name

我有这个自动取款机:

var http = new XMLHttpRequest();
httpPost.onreadystatechange = function(err) {
        if (httpPost.readyState == 4 && httpPost.status == 200){
            console.log(httpPost.responseText);
        } else {
            console.log(err);
        }
    }
var  path = "http://127.0.0.1:8000/uploadImage/"+name;
httpPost.open("POST", path, true);
// I guess I have to add the imagedata into the httpPost here, but i dont know how
httpPost.send(null);

然后在服务器端的路径上,将调用以下方法,并且我希望将base64编码图像的URL存储在mongodb中。我该如何从httpPost访问该图像?

function postNewImageType(req, res, next){
    var newImageTypeData = {
         name: req.params.name,
         image: "placeholder.png"
    }
    var data = // how to access the image?
    var imageBuffer = decodeBase64Image(data);
    fs.writeFile(cfg.imageFolger+newImageTypeData._id+'.jpeg', imageBuffer.data, function(err){
        if (err) return new Error(err);
        newImageTypeData.set({image:newImageTypeData._id+'.jpeg'});
        var image = new ImageType(newImageData);

    });
    imagetype.save(function (err) {
        if (error) {return next(new restify.InvalidArgumentError(JSON.stringify(error.errors)));}
        else { res.send(201, imagetype);}
    });   
}
1个回答

29

有几种方法可以将图像数据通过请求发送到服务器,但所有方法都需要使用 XMLHttpRequest 对象的 send 方法,并将要发送的数据作为其参数来调用。

send 方法会将请求分派到远程服务器,并将其参数设置为该请求的正文。由于您的服务器上期望的是 Base64 编码的图像数据,因此您首先需要在客户端将图像文件转换为 Base64 数据。

在客户端将图像转换为 Base64 的最简单方法是将图像作为图像元素加载,将其绘制到画布元素上,然后获取画布图像数据的 Base64 表示形式。

以下示例展示了实现方法(假设原始图像的 URL 存储在名为 imgsrc 的变量中,并且所需名称存储在 name 中):

// This function accepts three arguments, the URL of the image to be 
// converted, the mime type of the Base64 image to be output, and a 
// callback function that will be called with the data URL as its argument 
// once processing is complete

var convertToBase64 = function(url, imagetype, callback){

    var img = document.createElement('IMG'),
        canvas = document.createElement('CANVAS'),
        ctx = canvas.getContext('2d'),
        data = '';

    // Set the crossOrigin property of the image element to 'Anonymous',
    // allowing us to load images from other domains so long as that domain 
    // has cross-origin headers properly set

    img.crossOrigin = 'Anonymous'

    // Because image loading is asynchronous, we define an event listening function that will be called when the image has been loaded
    img.onLoad = function(){
        // When the image is loaded, this function is called with the image object as its context or 'this' value
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        data = canvas.toDataURL(imagetype);
        callback(data);
    };

    // We set the source of the image tag to start loading its data. We define 
    // the event listener first, so that if the image has already been loaded 
    // on the page or is cached the event listener will still fire

    img.src = url;
};

// Here we define the function that will send the request to the server. 
// It will accept the image name, and the base64 data as arguments

var sendBase64ToServer = function(name, base64){
    var httpPost = new XMLHttpRequest(),
        path = "http://127.0.0.1:8000/uploadImage/" + name,
        data = JSON.stringify({image: base64});
    httpPost.onreadystatechange = function(err) {
            if (httpPost.readyState == 4 && httpPost.status == 200){
                console.log(httpPost.responseText);
            } else {
                console.log(err);
            }
        };
    // Set the content type of the request to json since that's what's being sent
    httpPost.setHeader('Content-Type', 'application/json');
    httpPost.open("POST", path, true);
    httpPost.send(data);
};

// This wrapper function will accept the name of the image, the url, and the 
// image type and perform the request

var uploadImage = function(src, name, type){
    convertToBase64(src, type, function(data){
        sendBase64ToServer(name, data);
    });
};

// Call the function with the provided values. The mime type could also be png
// or webp

uploadImage(imgsrc, name, 'image/jpeg')

当您的服务器接收到请求时,请求体将包含包含Base64图像数据的JSON字符串。由于您未提供用于Mongo的服务器框架或数据库驱动程序,我假设您在应用程序中使用Express和Mongoose,并已定义了一个ImageType模型。

由于您始终可以从图像记录的_id属性和图像文件夹路径构造文件名,因此将其保存为记录上的属性并不一定有意义,但我在此保留了该功能,这将要求您在一个请求周期内将记录保存两次。

我还更改了处理来自文件系统调用的任何错误的方式。您从文件系统错误中获得的“err”已经是错误对象,需要以某种方式由服务器处理。

function postNewImageType(req, res, next){
    var json = JSON.parse(req.body),
        newImageTypeData = {
            name: json.name,
            image: "placeholder.png"
        },
        imageBuffer = decodeBase64Image(data),
        newImageType = new ImageType(newImageTypeData);

    //First we save the image to Mongo to get an id

    newImageType.save(function(err){
        if(err) return next(new restify.InvalidArgumentError(JSON.stringify(err.errors)));
        var fileName = cfg.imageFolder + newImageType._id + '.jpeg';

        fs.writeFile(fileName, imageBuffer.data, function(err){
            //Handle error in next middleware function somehow
            if (err) return next(err);
            newImageType.set({image: 'filename.png'});
            newImageType.save(function(err){
                if (err) return next(new restify.InvalidArgumentError(JSON.stringify(err.errors)));
                res.send(201, imagetype);
            });
        })
    });
}

1
非常感谢!这真的帮助我最终发送和保存了一张图片!代码中有一些小错误,但在您的帮助下,我成功解决了所有问题。另外还要点个赞,因为我没有对我使用的框架进行足够的解释。 - MojioMS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接