当前位置: 首页 > 面试题库 >

通过Web服务下载文件,然后通过Node / Express将其推送到Azure Blob存储

周鸿运
2023-03-14
问题内容

我需要从供应商的Web服务中检索文件,并将它们推送到唯一的blob容器中,以便用户拥有唯一的“工作区”。本质上,我将从供应商处获取文件,并且用户可以通过自己的Blob容器中的文件进行编辑,以免彼此交叉工作文件。我有唯一的blob容器,但需要从供应商的API中“下载”
/获取文件,并将其推送到blob容器中。我能够成功检索文件,这将是分别获取PDF,文本文件和图像的调用……但是,如果尝试将它们上传到Azure
Blob存储,则在Node.js中会出现以下错误:

TypeError:无法读取null的属性“ length”

我认为我需要在客户端将文件编码为base64才能正确获取长度,并且已经看到了一些使用具有toDataURL的Canvas的示例,但是不确定这是否是从本质上直接下载并推送至的最佳方法。
Azure Blob存储,尤其是因为我有PDF之类的文件(不确定PDF是否可以使用base64编码)。

这是调用服务的我的AngularJS控制器(请注意,实际端点可能会根据调用的文件而有所不同,因此我正在使用文件的客户端GET来控制用户可以以表格形式输入的变量):

$scope.getFiles = function () {

$.ajax({
url: 'http://vendorwebservice.net/ws/file1',
type: "GET",
success: function (result) {
console.log(result);
var filename = 'Texture_0.png';

$http.post('/postFile', { filename: filename, file: result }).success(function (data) {
console.log(data);
}, function (err) {
console.log(err);
});

alert("Files Retrieved!");
},
error: function (error) {
console.log("Failed to download image!");
}
})
}

这是我的后端/节点/快速代码:

app.post('/postFile', function (req, res, next) {
    var filename = req.body.filename;
    var file = req.body.file;
    var base64Data;
    fileBuffer = decodeBase64Image(file);
    blobSvc.createBlockBlobFromText('blob5', filename, fileBuffer.data, { 'contentType': fileBuffer.type }, function (error, result, response) {
        if (!error) {
            console.log("Uploaded" + result);
        }
        else {
            console.log(error);
        }
    });
})

// Decode file for upload
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;
}

更新1:
根据加里(Gary)的建议,我尝试了以下操作,但由于我的供应商API没有文件URI,而是在GET上生成文件的端点(又使我迷失了如何传递端点),因此使代码有些混乱与加里(Gary)的例子很有意义)。例如,我的供应商端点“
http://vendorapi.net/ws/texture_0
”返回一个名为“ Texture_0.png”的文件。

前端角度代码:

 $scope.getFromVendor = function () {
            var filename = 'Texture_0.png';//jpg,txt...
            $http.post('/uploadapifiles', { filename: filename, url: 'http://vendorapi.net/ws/texture_0' }).success(function (data) {
                console.log(data);
            }, function (err) {
                console.log(err);
            });
        }

服务器端下载处理(我认为这是最混乱的过程:

app.get(http://vendorapi.net/ws/texture_0', function (req, res, next) {
    res.download('http://vendorapi.net/ws/texture_0' + req.params.filename);
})

服务器端上传处理:

app.post('/uploadapifiles', function (req, res, next) {

    var filename = req.body.filename;
    var r = request(req.body.url).pipe(fs.createWriteStream('http://vendorapi.net/ws/texture_0' + filename))
    r.on('close', function () {
        blobsrv.createBlockBlobFromLocalFile('blob5', filename, 'http://vendorapi.net/ws/texture_0' + filename, function (error, result, response) {
            if (!error) {
                console.log("Uploaded" + result);
            }
            else {
                console.log(error);
            }
        });
    })
});

问题答案:

按照您的原始想法,首先您需要在客户端获取文件内容数据,然后将数据发布到Express Web服务器。

如果您获取的文件很大,则会减慢您的站点速度,因为文件数据将通过HTTP传输两次,并且可能会发生其他问题。

此外,在我的测试项目中,几乎不直接处理文件内容数据。

因此,我尝试了另一种想法作为解决方法。

我只是将获取特定文件的API发布到服务器,将文件另存为文件保存在服务器目录中,然后将文件上传到服务器端的存储。这是我的代码段:

角形前端:

$scope.upload =function(){
    var filename = (new Date()).getTime()+'.pdf';//jpg,txt...
    $http.post('http://localhost:1337/uploadfile', { filename: filename, url: 'http://localhost:1337/output/123.pdf'}).success(function (data) {
        console.log(data);
    },function(err){
        console.log(err);
    });
  }

后端:

我怀疑您获取文件形式的API会像后面一样。

router.get('/output/:filename', function (req, res, next) {
    res.download('upload/'+req.params.filename);
})

后请求处理程序利用包请求,并且无需弄清文件类型或编码类型,createBlockBlobFromLocalFile便会将文件上传到您在Blob存储上提供的位置,API参考:

router.post('/uploadfile', function (req, res, next) {
    var request = require('request');
    var filename = req.body.filename;
    var tmpFolder = 'upload/', //this folder is to save files download from vendor URL, and should be created in the root directory previously. 
        tmpFileSavedLocation = tmpFolder + filename; //this is the location of download files, e.g. 'upload/Texture_0.png'
    var r = request(req.body.url).pipe(fs.createWriteStream(tmpFileSavedLocation))//this syntax will download file from the URL and save in the location asyns
   r.on('close', function (){
        blobsrv.createBlockBlobFromLocalFile('vsdeploy', filename, tmpFileSavedLocation, function (error, result, response) {
            if (!error) {
                console.log("Uploaded" + result);
           }
            else {
                console.log(error);
            }
        });
    })

})


 类似资料:
  • 问题内容: 我有这个简单的服务器/客户端应用程序。我正在尝试让服务器通过OutputStream(FileOutputStream,OutputStream,ObjectOutputStream等)发送文件并在客户端将其接收,然后再将其保存到实际文件中。问题是,我尝试这样做,但一直失败。每当我创建文件并将从服务器接收到的对象写入文件时,都会得到损坏的图像(我只是将其另存为jpg,但这无关紧要)。这

  • 问题内容: 由于我是Web服务的新手,请您告诉我问题的答案。我的问题是 我想实现一个Web服务,当客户端调用此Web服务时,该服务会向客户端发送pdf文件。 请有人帮我提供一段不错的代码或解释。 现在可以请一个人解决我的错误。 12-23 09:42:48.429:调试/安装(32):DexInv:-开始’/data/app/vmdl33143.tmp’— 12-23 09:42:51.708:调

  • 我有一个基于Spring(Spring Security,Spring控制器和MVC)的项目,所以在我的超文本标记语言页面中,我必须允许文件下载。 我处理事件并使用基于jquery插件的代码 在我的控制器中: 但它在Spring Security性方面有问题,比如这个post x-frame,在internet explorer上不起作用。那么,有没有一种不用插件就能下载存储在我服务器上的文件的方

  • 我目前有问题下载到函数tmp dir下面是我的代码。函数返回

  • 问题内容: 我在服务器端有一个Struts2操作,用于文件下载。 但是,当我使用jQuery调用操作时: 在Firebug中,我看到数据是通过 Binary流 检索的。我想知道如何打开 文件下载窗口 ,用户可以用它在本地保存文件吗? 问题答案: 这是我现在建议的一些注意事项: 需要相对较新的浏览器 如果预期文件 很大,则 您可能应该执行与原始方法(iframe和cookie)类似的操作,因为以下某

  • 我试图使简单的文件服务器。我有Node.js后端与MongoDB GridFS存储存储文件。我从服务器获取文件通过。在前端,我使用Angular。我有两个主要问题: 当我使用Blob提供下载服务时,变成:“d1c393df-b0d9-4ae5-befe-8d45b183eb54…”友善的我读了很多关于它的文档,没有找到任何解决方案 当我只通过Express提供下载服务而不进行身份验证时,文件会正确