我们正在尝试创建一个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"); } }
它显示错误
请求'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 }); }
但面对这个问题
{"error":"函数createFileFromStream的参数流应该是一个对象"}
我是node.js的新手.请帮我解决这个问题.
这里有几个问题.让我们逐一介绍它们.
1.在Java客户端中,您不能只将二进制数据转储到Azure移动服务连接中.
这样做的原因是Azure移动服务有两个主体解析器,无论如何都可以确保为您解析请求主体.因此,虽然您可以通过指定不常见的内容类型来遍历Express正文解析器,但您仍然会通过天真地假设它是UTF-8字符串来点击Azure主体解析器,这会破坏您的数据流.
因此,唯一的选择是通过指定无法处理的内容类型跳过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.
请记住,因为您将数据作为Base64编码传输,您必须考虑到这种开销.因此,要支持上传大小为20Mb的文件,您必须设置MS_MaxRequestBodySizeKB
为大约20*1024*4/3 = 27307.