Javascript 如何在javascript中使用http.post将图像发送到服务器并在mongodb中存储base64
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34972072/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to send image to server with http.post in javascript and store base64 in mongodb
提问by MojioMS
I have trouble getting into http requests on the client-side storing images on the server-side using mongodb. I appreciate help a lot. I need an easy example of how i add an image file as data into a http post request such as XMLhttprequest. Lets say, I know the url of the servermethod. The source of the image is defined in
我在使用 mongodb 在服务器端存储图像时无法进入客户端的 http 请求。我非常感谢帮助。我需要一个简单的示例来说明如何将图像文件作为数据添加到 http post 请求(例如 XMLhttprequest)中。可以说,我知道 servermethod 的 url。图像的来源定义在
imgsrc
a name of the file is stored in
文件名存储在
name
I have this atm:
我有这个自动取款机:
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);
Then on the serverside at the path, the following method will be called and I want to store the url of the base64-encoded image in mongodb. How do I access the image from the httpPost?
然后在路径的服务器端,将调用以下方法,我想将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);}
});
}
回答by RickyTomatoes
There are a number of ways that you can send your image data in the request to the server, but all of them will involve calling the send
method of your XMLHttpRequest object with the data you wish to send as its argument.
有多种方法可以将请求中的图像数据发送到服务器,但所有这些send
方法都涉及调用XMLHttpRequest 对象的方法,并将您希望发送的数据作为其参数。
The send
method both dispatches the request to the remote server, and sets its argument as the body of that request. Since you're expecting Base64 encoded image data on your server, you'll first need to convert your image file to Base64 data on the client.
该send
方法将请求分派到远程服务器,并将其参数设置为该请求的正文。由于您希望在服务器上使用 Base64 编码的图像数据,因此您首先需要在客户端将图像文件转换为 Base64 数据。
The simplest way to convert an image to Base64 on the client is by loading the image as an image element, drawing it to a canvas element, and then getting the Base64 representation of the canvas's image data.
在客户端将图像转换为 Base64 的最简单方法是将图像作为图像元素加载,将其绘制到画布元素,然后获取画布图像数据的 Base64 表示。
That might look something like the following (given that the URL for the original image is stored in a variable named imgsrc
, and the desired name is stored in name
as stated):
这可能类似于以下内容(假设原始图像的 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')
When the request is received by your server, the request body will contain the JSON string with your Base64 image within it. Since you haven't provided the server framework or database driver you're using for Mongo, I've adapted your code assuming that you're using Express and Mongoose with an ImageType model already defined in your application.
当您的服务器收到请求时,请求正文将包含带有 Base64 图像的 JSON 字符串。由于您尚未提供用于 Mongo 的服务器框架或数据库驱动程序,因此我已经调整了您的代码,假设您使用 Express 和 Mongoose 以及已在应用程序中定义的 ImageType 模型。
Since you can always construct the file name of the image record from its _id
property and your image folder path, it doesn't necessarily make sense to save that as a property on the record, but I've preserved that functionality here, which will require you to save your record twice in one request cycle.
由于您始终可以根据图像记录的_id
属性和图像文件夹路径构造图像记录的文件名,因此将其保存为记录中的属性不一定有意义,但我在这里保留了该功能,这将需要您可以在一个请求周期内两次保存您的记录。
I've also changed the way any errors from the filesystem call are handled. The 'err' you get back from a filesystem error is already an Error object, and will need to be handled by your server in some way.
我还改变了处理来自文件系统调用的任何错误的方式。您从文件系统错误中返回的 'err' 已经是一个 Error 对象,需要由您的服务器以某种方式处理。
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);
});
})
});
}