正如标题所暗示的,这是一个有趣的用例。我有一个 HTML5 Canvas,可以将其转换为图像。我使用 AngularJS 作为前端,使用 Node/Express 作为我网站的后端。将 HTML5 Canvas 转换为图像按预期工作,我可以使用 jQuery AJAX(不使用 Node/Express)将其上传到单独的 Web 服务,如下所示:

 $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 存储的 Node/Express 代码,其中/upload 在 HTML5 表单的表单操作上调用:

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 Canvas 传递到“幕后”,用户不必通过 Web 表单下载并重新上传 HTML5 Canvas 图像,只需单击即可转换 Canvas,并且图像上传到 Azure(请参阅上面的第一个示例,了解使用不同 Web 服务的工作示例,该 Web 服务不使用 Node/Express,上传通过 jQuery AJAX 转换为图像的 HTML5 Canvas)。本质上,由于我使用 Node/Express 来管理 Azure Blob 存储,因此我希望上传功能能够在我的 jQuery AJAX 示例中运行。

我设想可以将图像数据/变量传递回 Node/Express,如下所示:

AngularJS 前端 Controller 代码(与名为“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); 
}); 
} 

Node/Express 后端代码:

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 错误:

Error: Required argument blob for function createBlockBlobFromFile is not defined

我还将“文件名”和"file"记录到 Node 控制台并得到“未定义”。

客户端我在浏览器控制台中收到 500 内部服务器错误。然而,使用“网络”选项卡,我进行了更深入的挖掘,发现“请求有效负载”的"file"采用了 base64 编码,并且“文件名”是正确的。

我很大程度上怀疑我没有正确地将变量传递给 Node/Express,这就是导致 Azure 调用失败的原因。我还想知道既然通过输入表单上传图像是否适用于 Azure/Node,我是否应该以某种方式将转换后的 Canvas 作为表单数据传递,但不确定如何实现这一点/应该尝试它。

我的问题是,如何传递正确的变量/数据,以便我的 Canvas 可以从 AngularJS 前端上传到 Azure Blob 存储到 Node/Express 后端?

请您参考如下方法:

我有一个测试项目来满足您的要求。我认为有几个关键点需要注意。

Node/Express 后端部分:

要在 Express 中获取 POST 数据,我们可以利用 bodyParser 中间件,它是 Express 框架的内部部分。

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。

如果您的服务器托管在 Azure 上,也许您会遇到 CROS 问题。所以我们需要在express.js框架中允许跨域资源共享。

这是我的代码片段:

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); 
        }); 
    } 


评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!