node.js - 使用 node.js 在 Azure 文件存储中上传文件

标签 node.js azure azure-storage azure-mobile-services azure-storage-files

我们正在尝试创建一个 Web 服务,以使用 node.js 服务将文件上传到 Azure 文件存储。

下面是node.js服务器代码。

exports.post = function(request, response){
var shareName = request.headers.sharename;
var dirPath = request.headers.directorypath;
var fileName = request.headers.filename;

var body;
var length;

request.on("data", function(chunk){
    body += chunk;
    console.log("Get data");
});


request.on("end", function(){
    try{
        console.log("end");
        var data = body;
        length = data.length;

console.log(body); // This giving the result as undefined
console.log(length);

        fileService.createFileFromStream(shareName, dirPath, fileName, body, length, function(error, result, resp) {
            if (!error) {
                // file uploaded
                response.send(statusCodes.OK, "File Uploaded");
            }else{
                response.send(statusCodes.OK, "Error!");
            }
        });

    }catch (er) {
response.statusCode = 400;
return res.end('error: ' + er.message);
}

});

}

下面是我们的客户端上传文件。

private static void sendPOST() throws IOException {
    URL obj = new URL("https://crowdtest-fileservice.azure-mobile.net/api/files_stage/");
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("POST");
    con.setRequestProperty("sharename", "newamactashare");
    con.setRequestProperty("directorypath", "MaheshApp/TestLibrary/");
    con.setRequestProperty("filename", "temp.txt");


    Path path = Paths.get("C:/Users/uma.maheshwaran/Desktop/Temp.txt");
    byte[] data = Files.readAllBytes(path);

    // For POST only - START
    con.setDoOutput(true);
    OutputStream os = con.getOutputStream();
    os.write(data);
    os.flush();
    os.close();
    // For POST only - END

    int responseCode = con.getResponseCode();
    System.out.println("POST Response Code :: " + responseCode);

    if (responseCode == HttpURLConnection.HTTP_OK) { // success
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
            System.out.println(inputLine);
        }
        in.close();

        // print result
        System.out.println(response.toString());
    } else {
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
        String line = "";
        while ((line = br.readLine()) != null) {
            System.out.println(line);
        }
        System.out.println("POST request not worked");
    }
}

显示错误

The request 'POST /api/files_stage/' has timed out. This could be caused by a script that fails to write to the response, or otherwise fails to return from an asynchronous call in a timely manner.

更新:

我也尝试过下面的代码。

  var body = new Object();
  body = request.body;
  var length = body.length;

  console.log(request.body);
  console.log(body);
  console.log(length);

    try {
        fileService.createFileFromStream(shareName, dirPath, fileName, body, length, function(error, result, resp) {
            if (!error) {
                // file uploaded
                response.send(statusCodes.OK, "File Uploaded");
            }else{
                response.send(statusCodes.OK, "Error!");
            }
        });
    } catch (ex) {
            response.send(500, { error: ex.message });
    }

但是面临这个问题

{"error":"Parameter stream for function createFileFromStream should be an object"}

我是 Node.js 新手。请帮我解决这个问题。

最佳答案

这里有几个问题。让我们一一回顾一下。

<强>1。在 Java 客户端中,您不能仅将二进制数据转储到 Azure 移动服务连接中。

原因是 Azure 移动服务有两个正文解析器,可确保无论如何都会为您解析请求正文。 因此,虽然您可以通过指定不常见的内容类型来绕过 Express 正文解析器,但您仍然会遇到 Azure 正文解析器,它会天真地假设它是 UTF-8 字符串,从而弄乱您的数据流。

因此,唯一的选择是通过指定 Express 解析器无法处理的内容类型来跳过 Express 解析器,然后通过使用 Base64 编码对二进制数据进行编码来与 Azure 解析器一起使用。

所以,在Java客户端中替换

Path path = Paths.get("C:/Users/uma.maheshwaran/Desktop/Temp.txt");
byte[] data = Files.readAllBytes(path);

con.setRequestProperty("content-type", "binary");    
Path path = Paths.get("C:/Users/uma.maheshwaran/Desktop/Temp.txt");
byte[] data = Files.readAllBytes(path);
data = Base64.getEncoder().encode(data);

如果您使用的不是 Java 8,请将 java.util.Base64 编码器替换为您有权访问的任何其他 Base64 编码器。

<强>2。您尝试使用的 createFileFromStream Azure 存储 API 函数需要一个流。

同时,手动解析请求正文时可以获得的最好结果是字节数组。不幸的是,Azure 移动服务使用 NodeJS 版本 0.8,这意味着没有简单的方法从字节数组构造可读流,并且您必须组装适合 Azure 存储 api 的自己的流。一些管道胶带和[email protected]应该没问题。

var base64 = require('base64-js'),
    Stream = require('stream'),
    fileService = require('azure-storage')
        .createFileService('yourStorageAccount', 'yourStoragePassword');

exports.post = function (req, res) {
    var data = base64.toByteArray(req.body),
        buffer = new Buffer(data),
        stream = new Stream();
        stream['_ended'] = false;
        stream['pause'] = function() {
            stream['_paused'] = true;
        };
        stream['resume'] = function() {
            if(stream['_paused'] && !stream['_ended']) {
                stream.emit('data', buffer);
                stream['_ended'] = true;
                stream.emit('end');
            }
        }; 
    try {
        fileService.createFileFromStream(req.headers.sharename, req.headers.directorypath, 
            req.headers.filename, stream, data.length, function (error, result, resp) {
                res.statusCode = error ? 500 : 200;
                res.end();
            }
        );
    } catch (e) {
        res.statusCode = 500;
        res.end();
    }
};

这些是此示例所需的依赖项。

"dependencies": {   
    "azure-storage": "^0.7.0",
    "base64-js": "^0.0.8",
    "stream": "0.0.1"
}

如果在服务的 package.json 中指定它们不起作用,您可以随时转到此 link并通过控制台手动安装它们。

cd site\wwwroot
npm install azure-storage
npm install base64-js
npm install <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ddaea9afb8bcb09dedf3edf3ec" rel="noreferrer noopener nofollow">[email protected]</a>

<强>3。要增加 1Mb 的默认上传限制,请为您的服务指定 MS_MaxRequestBodySizeKB。

MS_MaxRequestBodySizeKB

请记住,由于您是以 Base64 编码传输数据,因此您必须考虑此开销。因此,要支持上传最大 20Mb 的文件,您必须将 MS_MaxRequestBodySizeKB 设置为大约 20 * 1024 * 4/3 = 27307。

关于node.js - 使用 node.js 在 Azure 文件存储中上传文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34331893/

相关文章:

node.js - 仅从 Sequelize ORM 中获取 dataValues

arrays - Nodejs中通过for循环构造数组

javascript - 无法运行本地主机:3000 on meanstack MEANIO, https ://github. com/linnovate/mean

azure - 修改 Azure WebJob 上的计划

azure - 从 Azure Devops 托管代理访问私有(private)存储帐户

azure - 查询azure表以获取分区的最后插入数据

azure - 无法从 Java 进程将消息添加到 Azure 模拟器

javascript - NodeJs 和 MySQL 时间戳

javascript - 无法启动Azure中托管的nodejs Web api

azure - 以下团队项目收集已停止...开始收集然后重试