我想在Windows Azure上做一個網站,它允許用戶通過網頁提交一個文件與窗體,發送窗體與POST方法。我正在使用mac操作系統的最新版本,在mac book air 2013上。上傳,然後下載一個大文件,與Windows Azure,blob存儲和nodejs
服務器接收到此表單,將文件流式傳輸到blob,並將用戶重定向到帶有指向blob鏈接的新網頁(這是公開的)。這樣,用戶可以稍後獲得他的文件。
我所做的似乎可以很好地處理小文件(一個映像〜35KB,一個dmg文件〜950MB)。
但是,當涉及到更大的文件(〜20MB)時,服務器發現上傳過程中出現錯誤(約1分20秒或2分40秒,不記得)。客戶端(谷歌瀏覽器)似乎沒有意識到它,並繼續上傳文件。但是當它結束時,它會顯示503錯誤。我嘗試了2個大約20MB的dmg文件,並得到了相同的結果(問題1)。
然後使用一個〜57MB dmg文件(谷歌瀏覽器安裝程序)和幾個〜700MB文件(使用〜30MB/s上傳互聯網訪問),服務器似乎沒有任何問題,也沒有客戶端。上傳過程直到結束,並且我獲得了存儲在blob存儲中的文件的鏈接。但是當我下載它時,文件比預期的要大一點(57MB文件多了4096字節,大約700MB文件大約40KB)。我嘗試了幾種類型的文件:能夠重放視頻(儘管有些奇怪的東西)是足夠好的,但當我嘗試它時,dmg無法掛載(我猜是因爲完整性檢查很好地工作)(問題2 )
我想知道哪些數據已添加到我的文件中。所以我創建了2個與我的〜57MB dmg文件大小相同的文件。第一個是滿了字符0,秒數是0和1交替。當我上傳並下載它們時,它們沒有原始大小,但它們仍然只包含000000 ....或010101010 ....雖然,真的有更多0000 ...和更多0101010 ....比原始版本(但只有0和01)。
所以我去了blob存儲管理頁面,我看到每個文件的大小似乎比我的電腦上小(例如:54.33MB,而不是〜57MB)。可能是因爲不同的文件系統,...?
讓我們總結一下問題2:我上傳了一個大文件,它看起來比我的筆記本電腦小,然後我下載它,實際上它比原來的版本更大。奇怪,不是嗎?
任何想法?謝謝你的幫助 !
這裏是我的server.js文件:
var http = require('http');
var url = require("url");
var express = require('express');
var querystring = require('querystring');
var fs = require('fs');
var path = require('path');
var azure = require('azure');
var multiparty = require('multiparty');
var tools = require('./tools.js');
var app = express();
app.use(express.logger("dev"));
var port = process.env.PORT || 1337;
var containerName = 'publicblobs';
app.use('/public', express.static('./public'));
/*
* \brief Displays upload form
*/
app.get('(/|/upload/?)', function(req, res) {
res.redirect('/public/upload.html');
});
/*
* \brief Handles upload post request.
*/
app.post('/upload/request/?', function (req, res) {
var blobService = azure.createBlobService();
var form = new multiparty.Form();
var currentFileName = 'undefinedCurrentFileName';
blobService.createContainerIfNotExists(containerName
, {publicAccessLevel : 'blob'}
, function(error){
if(!error){
// Container exists and is public
} else {
res.render('log.ejs', {log: error.message});
}
});
function gotPart(part) {
if (part.filename) {
console.log("New file received !");
currentFileName = part.filename;
var size = part.byteCount;
console.log("file size : " + size);
var onError = function(error) {
if (error) {
console.log("blobService.createBlockBlobFromStream : on error");
res.render('log.ejs', {log: error.message});
} else {
console.log("onError() : No error");
}
};
blobService.createBlockBlobFromStream(containerName, currentFileName, part, size, onError);
} else {
console.log("New part received (not a file)");
form.handlePart(part);
}
}
form.on('part', gotPart);
function reqEnd() {
console.log("Upload completed!");
res.redirect('/upload/complete/?'+
// 'url='+req.get('host')+'/library/download/'+targetFileName+//'+req.get('host')+'
'&fileName='+currentFileName+
'&result=success');
}
req.on('end', reqEnd);
function handleErrorCallback(error) { // inspired from http://stackoverflow.com/questions/18367824/how-to-cancel-http-upload-from-data-events
var errorLog = "There was an error while receiving the request. The client may have put an end to the connection : " + error;
console.log(errorLog);
}
req.on('error', handleErrorCallback);
form.on('error', handleErrorCallback);
form.parse(req);
});
/*
* \brief Returns the file to the user.
*/
app.get('/library/download/:fileName', function(req, res) {
fs.readFile('./public/uploaded/'+req.params.fileName, function(error,data){
res.end(data);
});
});
/*
* \brief Inform the user about his uploaded file (and about error if need be)
*/
app.get('/upload/complete/?', function(req, res) {
var params = querystring.parse(url.parse(req.url).query);
res.setHeader('Content-Type', 'text/html');
res.charset = 'utf8';
if (params['result'] === 'success') {
res.render('uploadComplete.ejs', {log: 'File '+params['fileName']+' uploaded to ', url: url.parse('http://'+process.env['AZURE_STORAGE_ACCOUNT']+'.blob.core.windows.net/'+containerName+'/'+params['fileName']).href});
} else {
res.render('uploadComplete.ejs', {log: 'An error occurred while uploading '+params['fileName']+' : '+params['log'], url: ''});
}
});
/*
* \brief Handles wrong addresses
*/
app.use(function(req, res, next){
res.setHeader('Content-Type', 'text/plain');
res.charset = 'utf8';
console.log("Redirection due to the fact that the page has not been found.");
res.redirect('/upload');
});
app.listen(port);
這裏使用的引導和jQuery我的形式:
<div class="container">
<div class="starter-template">
<form class="form-signin" role="form" action="/upload/request" method="post" enctype="multipart/form-data">
<h2 class="form-signin-heading">Select a file to upload</h2>
<label>
<input type="file" name="filename2" id="filename2" class="form-control" required>
</label>
<button class="btn btn-lg btn-primary btn-block" type="submit">Upload</button>
</form>
</div>
,這裏是我的web.config文件:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^server.js\/debug[\/]?" />
</rule>
<rule name="StaticContent">
<action type="Rewrite" url="public{REQUEST_URI}"/>
</rule>
<rule name="DynamicContent">
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True"/>
</conditions>
<action type="Rewrite" url="server.js"/>
</rule>
</rules>
</rewrite>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1073741824"/>
</requestFiltering>
</security>
</system.webServer>
<system.web>
<httpRuntime maxRequestLength="2097152"/>
</system.web>
</configuration>
嗨我在10月份有類似的問題,因此不得不使用標準上傳(首先寫入服務器)。但是現在Azure現在允許CORS,所以我正在嘗試生成一個SAS URL並直接上傳到Azure,而不需要多方或第三方上載。我讓你知道它是怎麼回事。 –
嗨馬特,感謝您的評論。我正在嘗試CORS,以下是迄今爲止我已經結束的內容:http://stackoverflow.com/questions/22286856/windows-azure-set-blob-cors-properties-using-nodejs – user3380016
看看我的回答[類似問題](http://stackoverflow.com/questions/6877376/any-way-to-set-access-control-allow-origin-for-a-windows-azure-blob/23192353#23192353) – Agni