使用Node/Express将HTML5画布转换为图像上传到Azure [英] Upload HTML5 Canvas Converted to Image to Azure using Node/Express
问题描述
顾名思义,这是一个有趣的用例.我有一个HTML5画布,可以将其转换为图像.我将AngularJS用作前端,而在我的网站的后端使用Node/Express.将HTML5 Canvas转换为图像可以按预期工作,并且可以使用jQuery AJAX(不使用Node/Express)将其上传到单独的Web服务,如下所示:
As the title implies, this is an interesting use case. I have an HTML5 Canvas that I am able to convert to a image. I am using AngularJS as the front end, with Node/Express on the backend for my site. Converting the HTML5 Canvas to an image works as intended and I am able to upload this to a separate Web Service using jQuery AJAX (not using Node/Express) as follows:
$scope.webService = function () {
var send = function (blob) {
var filename = 'Test.pdf';
var formdata = new FormData();
formdata.append('File1', blob, filename);
$.ajax({
url: 'http://awebservice.net/endpoint',
type: "POST",
data: formdata,
mimeType: "multipart/form-data",
processData: false,
contentType: false,
crossDomain: true,
success: function (result) {
console.log("Upload complete!");
},
error: function (error) {
console.log("Something went wrong!");
}
})
}
var canvasImage = document.getElementById("c");
if (!canvasImage.toBlob) {
var dataURL = canvasImage.toDataURL();
var bytes = atob(dataURL.split(',')[1])
var arr = new Uint8Array(bytes.length);
for (var i = 0; i < bytes.length; i++) {
arr[i] = bytes.charCodeAt(i);
}
send(new Blob([arr], { type: 'image/png' }));
}
else
canvasImage.toBlob(send);
}
我在另一种情况下使用Node/Express,如果我使用带有提交按钮的标准输入表单,则可以通过Node将映像上传到Azure.这是上传到Azure Blob存储的节点/快速代码,用于用户通过文件输入和提交按钮手动上传的图像,其中在HTML5表单的表单操作中调用/upload:
I am using Node/Express in another scenario where I can upload an image to Azure via Node if I use a standard input form with a submit button. Here is the Node/Express code that uploads to Azure Blob Storage for an image manually uploaded by a user through an file input and submit button, where /upload is called on the form action of the HTML5 form:
app.post('/upload4', function (req, res) {
var form = new formidable.IncomingForm();
form.parse(req, function (err, fields, files) {
var options = {
contentType: files.myfile.type,
metadata: { fileName: files.myfile.name }
};
blobSvc.createBlockBlobFromLocalFile('blob5', files.myfile.name, files.myfile.path, options, function (error, result, response) {
if (!error) {
// file uploaded
res.send('file uploaded!');
}
});
});
console.log(req);
});
但是,我需要将转换后的HTML5画布传递到幕后",而用户不必通过Web表单下载并重新上传HTML5画布图像,而只需单击一下,即可对Canvas进行转换,图像上载到Azure(有关使用不使用Node/Express的不同Web服务的工作示例,请参见上面的第一个示例,该Web Service不上载通过jQuery AJAX转换为图像的HTML5 Canvas).本质上,由于我使用Node/Express来管理Azure Blob存储,因此我希望在jQuery AJAX示例中可以使用上载功能.
However, I need to pass my converted HTML5 Canvas "behind the scenes" where users don't have to download and re-upload the HTML5 Canvas Image via a Web form, but rather on click, the Canvas is converted and the image is uploaded to Azure (see first example above for a working example using a different Web Service that doesn't use Node/Express that uploads an HTML5 Canvas converted to an image via jQuery AJAX). Essentially, since I am using Node/Express to manage Azure Blob Storage, I want the upload functionality that works in my jQuery AJAX example.
我设想可以按以下方式将图像数据/变量传递回Node/Express:
I was envisioning that I could pass the image data/variables back to Node/Express as follows:
AngularJS前端控制器代码(与名为"upload()"的ng-click按钮操作绑定):
$scope.upload = function () {
var canvasImage = document.getElementById("c");
var img = canvasImage.toDataURL("image/png");
var filename = 'Texture_0.png';
$http.post('/upload', { filename: filename, file: img }).success(function (data) {
console.log(data);
});
}
节点/快速后端代码:
app.post('/upload', function (req, res) {
var filename = req.filename;
var file = req.file;
blobSvc.createBlockBlobFromLocalFile('mycontainer', filename, file, function (error, result, response) {
if (!error) {
console.log("Uploaded" + result);
// file uploaded
}
else {
console.log(error);
}
});
});
当我单击魔术按钮"以将Canvas转换为图像(图像转换有效)并上传(上传不起作用)时,出现如下Node错误:
When I click the "magic button" to convert the Canvas to an image (image conversion works) and upload (upload doesn't work), I get a Node error as follows:
错误:函数createBlockBlobFromFile的必需参数blob为 未定义
Error: Required argument blob for function createBlockBlobFromFile is not defined
我也将文件名"和文件"登录到节点控制台,并得到未定义".
I also logged "filename" and "file" to the Node console and got "undefined".
客户端在浏览器的控制台中,我收到500 Internal Server Error.但是,使用网络"选项卡,我进行了更深入的挖掘,发现请求有效负载"具有文件" base64编码和文件名"正确.
Client side I get a 500 Internal Server Error in the console of my browser. However, using the Network tab I dug deeper and saw that the "Request Payload" had the "file" base64 encoded and the "filename" as correct.
我很大程度上怀疑我没有将变量正确地传递给Node/Express,这就是导致Azure调用中断的原因.我也想知道自从通过输入表单上传图像是否适用于Azure/Node后,是否应该以某种方式将转换后的Canvas作为formdata传递,但不确定如何实现/应该尝试.
I largely suspect that I am not passing in the variables to Node/Express properly, and that is what is tripping up the Azure call. I am also wondering if since uploading an image via an input form works with Azure/Node, if I should somehow pass the converted Canvas as formdata but unsure how I would achieve this/should attempt it.
我的问题是,如何传递正确的变量/数据,以便将画布从AngularJS前端上传到Azure Blob存储到Node/Express后端?
My question is, how do I pass the right variables/data so my canvas can be uploaded to Azure Blob Storage from AngularJS front end to Node/Express backend?
推荐答案
我有一个测试项目可以解决您的需求.我认为应该注意几个关键点.
I had a test project to work out your requirements. And there are several key points I think should be noticed.
节点/快速后端部分:
要在Express中获取POST数据,我们可以利用曾经用作Express框架内部部分的bodyParser
中间件.
To get POST data in Express, we can leverage bodyParser
middle-ware which is used to be internal part of Express framework.
var bodyParser = require('body-parser');
var router = express.Router();
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({ extended: false }));
router.post('/postCanvas', function (req, res, next){
var filename = req.body.filename;
var file = req.body.file;
var base64Data;
fileBuffer = decodeBase64Image(file);
blobsrv.createBlockBlobFromText('container', filename, fileBuffer.data, {'contentType': fileBuffer.type}, function (error, result, response) {
if (!error) {
console.log("Uploaded" + result);
}
else {
console.log(error);
}
});
/*
fs.writeFileSync('upload/' + filename, fileBuffer.data);
blobsrv.createBlockBlobFromLocalFile('container', filename, 'upload/' + filename, function (error, result, response) {
if (!error) {
console.log("Uploaded" + result);
// file uploaded
}
else {
console.log(error);
}
});*/
})
function decodeBase64Image(dataString) {
var matches = dataString.match(/^data:([A-Za-z-+\/]+);base64,(.+)$/),
response = {};
if (matches.length !== 3) {
return new Error('Invalid input string');
}
response.type = matches[1];
response.data = new Buffer(matches[2], 'base64');
return response;
}
取消注释部分将通过base64字符串直接创建blob,注释部分将首先将图像另存为服务器上的文件,然后通过该文件创建blob.
The uncomment part will directly create a blob by base64 string, and the comment part will save the image as a file on server first, then create a blob by the file.
如果您的服务器托管在Azure上,则可能会遇到CROS问题.因此,我们需要允许在express.js
框架中使用corss起源的资源.
Maybe you will meet CROS problem if your server is hosted on Azure. So we need to allow corss-origin resource sharing in express.js
framework.
这是我的代码段:
app.use(function (req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "http://localhost:8801");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
});
棱角部分与您相同:
$scope.upload = function () {
var canvasImage = document.getElementById("myCanvas");
var img = canvasImage.toDataURL("image/jpeg");
var filename = 'Texture_0.jpg';
console.log(img);
console.log(filename);
$http.post('http://localhost:1337/postCanvas', { filename: filename, file: img }).success(function (data) {
console.log(data);
},function(err){
console.log(err);
});
}
这篇关于使用Node/Express将HTML5画布转换为图像上传到Azure的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!