I am trying to retrieve the URL of the file I just uploaded to Azure Storage using node.js. My code for the upload is this:
[Notes: I'm using Ember-droplet, so the 'zone' is where files are dragged and dropped. This is the server side code to handle the route where a POST request is sent in order to upload files. ]
// Responsible for the call to OPTIONS.
app.options('/upload', function(request, response) {
response.send(200);
});
/* Responsible for file upload. */
app.post('/fileUpload', function(request, response) {
/* Get the files dropped into zone. */
var files = request.files.file,
promises = [];
/**
* @method uploadFile
* @param file {Object}
* @return {Object}
* Function takes a general param file, creates a blob from it and returns the promise to upload it.
* Promise: jQuery promise = all done later.
*/
var uploadFile = function(file) {
var deferred = new Deferred();
// Actual upload code.
// Also replace 'profile-pictures with abstracted container name.'
blobService.createBlockBlobFromFile('profile-pictures', file.name, file.path, function(error, result, response) {
if (!error) {
deferred.resolve(file.name);
console.log("result:");
console.log(result);
console.log("response:");
console.log(response);
}
});
return deferred.promise;
};
if (!Array.isArray(files)) {
// We're dealing with only one file.
var promise = uploadFile(files);
promises.push(promise);
} else {
// We're dealing with many files.
files.forEach(function(file) {
var promise = uploadFile(file);
promises.push(promise);
});
}
var fileUrls = [];
// Send all files in the promise to execute.
promisedIo.all(promises).then(function(files) {
response.send({ files: files, success: true });
response.end();
});
});
I printed out the results and response and this is what I get:
result:
{ container: 'profile-pictures',
blob: 'robot.jpeg',
etag: '---blah---',
lastModified: 'Mon, 30 Jun 2014 14:38:09 GMT',
contentMD5: '---blah---',
requestId: '---blah---' }
response:
{ isSuccessful: true,
statusCode: 201,
body: '',
headers:
{ 'transfer-encoding': 'chunked',
'content-md5': '---blah---',
'last-modified': 'Mon, 30 Jun 2014 14:38:09 GMT',
etag: '"---blah---"',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-request-id': '---blah---',
'x-ms-version': '2014-02-14',
date: 'Mon, 30 Jun 2014 14:38:08 GMT' },
md5: undefined }
None of these seem to include the URL of the file I just posted; I'm not sure how to get the URL at all. Is there a method of blobservice I'm missing, or anything like that.
One 'solution' I found is to hardcode it with:
http:///blob.core.windows//blob-name,
But I feel unfortable with that. Is there a way to extract this URL and if so, how?
I am trying to retrieve the URL of the file I just uploaded to Azure Storage using node.js. My code for the upload is this:
[Notes: I'm using Ember-droplet, so the 'zone' is where files are dragged and dropped. This is the server side code to handle the route where a POST request is sent in order to upload files. ]
// Responsible for the call to OPTIONS.
app.options('/upload', function(request, response) {
response.send(200);
});
/* Responsible for file upload. */
app.post('/fileUpload', function(request, response) {
/* Get the files dropped into zone. */
var files = request.files.file,
promises = [];
/**
* @method uploadFile
* @param file {Object}
* @return {Object}
* Function takes a general param file, creates a blob from it and returns the promise to upload it.
* Promise: jQuery promise = all done later.
*/
var uploadFile = function(file) {
var deferred = new Deferred();
// Actual upload code.
// Also replace 'profile-pictures with abstracted container name.'
blobService.createBlockBlobFromFile('profile-pictures', file.name, file.path, function(error, result, response) {
if (!error) {
deferred.resolve(file.name);
console.log("result:");
console.log(result);
console.log("response:");
console.log(response);
}
});
return deferred.promise;
};
if (!Array.isArray(files)) {
// We're dealing with only one file.
var promise = uploadFile(files);
promises.push(promise);
} else {
// We're dealing with many files.
files.forEach(function(file) {
var promise = uploadFile(file);
promises.push(promise);
});
}
var fileUrls = [];
// Send all files in the promise to execute.
promisedIo.all(promises).then(function(files) {
response.send({ files: files, success: true });
response.end();
});
});
I printed out the results and response and this is what I get:
result:
{ container: 'profile-pictures',
blob: 'robot.jpeg',
etag: '---blah---',
lastModified: 'Mon, 30 Jun 2014 14:38:09 GMT',
contentMD5: '---blah---',
requestId: '---blah---' }
response:
{ isSuccessful: true,
statusCode: 201,
body: '',
headers:
{ 'transfer-encoding': 'chunked',
'content-md5': '---blah---',
'last-modified': 'Mon, 30 Jun 2014 14:38:09 GMT',
etag: '"---blah---"',
server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
'x-ms-request-id': '---blah---',
'x-ms-version': '2014-02-14',
date: 'Mon, 30 Jun 2014 14:38:08 GMT' },
md5: undefined }
None of these seem to include the URL of the file I just posted; I'm not sure how to get the URL at all. Is there a method of blobservice I'm missing, or anything like that.
One 'solution' I found is to hardcode it with:
http:///blob.core.windows//blob-name,
But I feel unfortable with that. Is there a way to extract this URL and if so, how?
Share Improve this question edited Aug 5, 2015 at 15:35 resueman 10.6k10 gold badges33 silver badges46 bronze badges asked Jun 30, 2014 at 15:02 DarshanDarshan 1,0113 gold badges16 silver badges28 bronze badges 4- 1 Couldn't resist--I still have my testbed sat around from the last question you posted :) – mpd106 Commented Jun 30, 2014 at 18:40
- Any joy? Did you get this working? – mpd106 Commented Jul 3, 2014 at 8:59
- Oh I didn't update this yet. I think it's working, but I've been stuck on another issue that has me held up - I replicated the example code from ember-droplet, but my xmlhttprequest never changes state from 1 to 4, so its not firing a response at all for some reason. I'd very much appreciate if you could take a look at it, if you don'd mind or course(I know its a bit imposing), but I cannot confirm until it's all working. stackoverflow./questions/24534623/… – Darshan Commented Jul 3, 2014 at 13:48
- I understand--I don't see any harm in having a go at reproducing it! – mpd106 Commented Jul 4, 2014 at 6:54
1 Answer
Reset to default 8It turns out that concatenating the strings is actually what the Azure library does under the hood--the destination path for your file is puted in this line:
webResource.uri = url.resolve(host, url.format({pathname: webResource.path, query: webResource.queryString}));
...from https://github./Azure/azure-storage-node/blob/master/lib/mon/lib/services/storageserviceclient.js. host
is a marginally transformed / normalised version of exactly what you pass in as the last parameter in your call to createBlobService
, and webResource.path
is, again, a normalised concatenation of the blob container name and blob name you pass in the call to createBlockBlobFromFile
.
Normalising all that stuff yourself reliably would be a pain, but thankfully you don't need to! Take a look at the blobService
object that you're calling createBlockBlobFromFile
on--there's a method getUrl
. If you call this with equivalent parameters to the ones used to create your file, e.g.
var containerName = 'mycontainer';
var hostName = 'https://mystorageaccountname.blob.core.windows';
var url = blobService.getUrl(containerName, file.name, null, hostName);
...you'll get the path that a blob with the specified name, host and blob container name would end up. Not quite as handy as having the path on some returned response object, but this does look like it will reliably perform all the same normalisation and formatting on the parts of the path that it performs when making the request. Just make sure to have a single instance of both containerName
and hostName
shared throughout your code in that file, and you should be good.