18

node.js サービスを使用して Azure ファイル ストレージにファイルをアップロードする Web サービスを作成しようとしています。

以下は、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");
    }
}

エラーを表示しています

リクエスト「POST /api/files_stage/」がタイムアウトしました。これは、スクリプトが応答への書き込みに失敗したか、非同期呼び出しからタイムリーに返されなかったことが原因である可能性があります。

更新しました:

以下のコードも試しました。

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

しかし、問題に直面している

{"エラー":"関数 createFileFromStream のパラメーター ストリームはオブジェクトでなければなりません"}

私はnode.jsが初めてです。これを修正するのを手伝ってください。

4

5 に答える 5

8

ここにはいくつかの問題があります。それらを1つずつ見ていきましょう。

1. Java クライアントでは、バイナリ データを Azure モバイル サービス接続にダンプすることはできません。

これは、Azure モバイル サービスに 2 つの本文パーサーがあり、何があっても要求本文が解析されるためです。そのため、一般的ではないコンテンツ タイプを指定して Express 本文パーサーを回避することはできますが、Azure 本文パーサーは、単純に UTF-8 文字列であると想定してデータ ストリームを台無しにしてしまいます。

したがって、唯一のオプションは、処理できないコンテンツ タイプを指定して 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 に適した独自のストリームを組み立てる必要があります。一部のダクト テープと stream@0.0.1 は問題なく動作するはずです。

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 でそれらを指定しても機能しない場合は、いつでもこのリンクにアクセスして、コンソールから手動でインストールできます。

cd site\wwwroot
npm install azure-storage
npm install base64-js
npm install stream@0.0.1

3. デフォルトのアップロード制限である 1Mb を増やすには、サービスに MS_MaxRequestBodySizeKB を指定します。

MS_MaxRequestBodySizeKB

ただし、Base64 でエンコードされたデータを転送しているため、このオーバーヘッドを考慮する必要があることに注意してください。MS_MaxRequestBodySizeKBしたがって、最大 20Mb のサイズのファイルのアップロードをサポートするには、おおよそ 20 * 1024 * 4 / 3 = 27307に設定する必要があります。

于 2016-01-04T22:42:14.933 に答える
3

で定義された関数にリクエストが到着すると、リクエストexports.post全体がすでにそこにあるため、バッファリングする必要はありません。以下のコードの行に沿って何かを書くことで、それを簡素化できます。

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

    var body = request.body;
    var length = body.length;

    console.log(length);

    try {
        fileService.createFileFromText(shareName, dirPath, fileName, body, 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 });
    }
}
于 2015-12-17T18:54:16.127 に答える