我有一个 Apache Cordova (PhoneGap) 应用程序,现在我想上传:照片、音频和视频到 Azure;正在审查post我发现可以使用 Azure 存储服务来完成此操作,但我找不到使用应用程序 Cordova (PhoneGap) 来完成此操作的文章或示例代码。
您可以使用应用程序 (PhoneGap) Cordova 上传此类文件吗?
最佳答案
这是一个包含项目示例的端到端可靠答案。
为了确保死链接不会让其他人陷入困境,这里是代码。
以下代码替换了“添加”按钮的原始提交事件处理程序,拍摄照片,使用捕获的图像中的信息设置项目的一些属性,然后调用 insertNewItemWithUpload():
// Handle insert--this replaces the existing handler.
$('#add-item').submit(function (evt) {
var textbox = $('#new-item-text'),
itemText = textbox.val();
if (itemText !== '') {
var newItem = { text: itemText, complete: false };
// Do the capture before we do the insert. If user cancels, just continue.
// Launch device camera application to capture a single image.
navigator.device.capture.captureImage(function (mediaFiles) {
if (mediaFiles) {
// Set a reference to the captured file.
var capturedFile = mediaFiles[0];
// Set the properties we need on the inserted item.
newItem.containerName = "todoitemimages";
newItem.resourceName = capturedFile.name;
// Insert the item and upload the blob.
insertNewItemWithUpload(newItem, capturedFile);
}
}, function () {
// Insert the item but not the blob.
insertNewItemWithUpload(newItem, null);
}, { limit: 1 });
}
textbox.val('').focus();
evt.preventDefault();
});
以下 insertNewItemWithUpload() 函数将新的 TodoItem 对象发送到移动服务:
// Insert a new item, then also upload a captured image if we have one.
var insertNewItemWithUpload = function (newItem, capturedFile) {
// Do the insert so that we can get the SAS query string from Blob storage.
todoItemTable.insert(newItem).then(function (item) {
// If we have obtained an SAS, then upload the image to Blob storage.
if (item.sasQueryString !== undefined) {
insertedItem = item;
readImage(capturedFile);
}
}, handleError).then(refreshTodoItems, handleError);
}
当插入的项目有containerName字段时,移动服务中的以下插入脚本(与教程基本相同)会生成SAS,用于将图像上传到Azure:
var azure = require('azure');
var qs = require('querystring');
var appSettings = require('mobileservice-config').appSettings;
function insert(item, user, request) {
// Get storage account settings from app settings.
var accountName = appSettings.STORAGE_ACCOUNT_NAME;
var accountKey = appSettings.STORAGE_ACCOUNT_ACCESS_KEY;
var host = accountName + '.blob.core.windows.net';
if ((typeof item.containerName !== "undefined") && (
item.containerName !== null)) {
// Set the BLOB store container name on the item, which must be lowercase.
item.containerName = item.containerName.toLowerCase();
// If it does not already exist, create the container
// with public read access for blobs.
var blobService = azure.createBlobService(accountName, accountKey, host);
blobService.createContainerIfNotExists(item.containerName, {
publicAccessLevel: 'blob'
}, function(error) {
if (!error) {
// Provide write access to the container for the next 5 mins.
var sharedAccessPolicy = {
AccessPolicy: {
Permissions: azure.Constants.BlobConstants.SharedAccessPermissions.WRITE,
Expiry: new Date(new Date().getTime() + 5 * 60 * 1000)
}
};
// Generate the upload URL with SAS for the new image.
/*var sasQueryUrl =
blobService.generateSharedAccessSignature(item.containerName,
item.resourceName, sharedAccessPolicy);*/
var sasQueryUrl =
blobService.generateSharedAccessSignature(item.containerName,
'', sharedAccessPolicy);
// Set the query string.
item.sasQueryString = qs.stringify(sasQueryUrl.queryString);
// Set the full path on the new new item,
// which is used for data binding on the client.
item.imageUri = sasQueryUrl.baseUrl + sasQueryUrl.path + '/'
+ item.resourceName;
} else {
console.error(error);
}
request.execute();
});
} else {
request.execute();
}
}
利用移动服务提供的 SAS,使用 PUT 请求(将 SAS 作为查询字符串)上传 JPEG 文件非常容易。事实证明,最好的方法是使用一个好的 XMLHttpRequest。首先,我需要获取本地存储的图像,该图像由相机捕获操作保存。以下代码使用捕获图像元数据来获取本地文件并将其读入数组缓冲区:
// This function is called to get the newly captured image
// file and read it into an array buffer.
function readImage(capturedFile) {
window.resolveLocalFileSystemURL(capturedFile.fullPath, function (fileEntry) {
fileEntry.file(function (file) {
// We need a FileReader to read the captured file.
var reader = new FileReader();
reader.onloadend = readCompleted;
reader.onerror = fail;
// Read the captured file into a byte array.
// This function is not currently supported on Windows Phone.
reader.readAsArrayBuffer(file);
}, fail);
});
}
读取操作完成后,二进制数组数据将作为 XMLHttpRequest 的正文发送:
// This function gets called when the reader is done loading the image
// and it is sent via an XMLHttpRequest to the Azure Storage Blob service.
var readCompleted = function (evt) {
if (evt.target.readyState == FileReader.DONE) {
// The binary data is the result.
var requestData = evt.target.result;
// Build the request URI with the SAS, which gives us permissions to upload.
var uriWithAccess = insertedItem.imageUri + "?" + insertedItem.sasQueryString;
var xhr = new XMLHttpRequest();
xhr.onerror = fail;
xhr.onloadend = uploadCompleted;
xhr.open("PUT", uriWithAccess);
xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
xhr.setRequestHeader('x-ms-blob-content-type', 'image/jpeg');
xhr.send(requestData);
}
}
完成示例中困难的上传部分后,最后要做的事情是确保图像与其项目一起显示。我首先必须调整 CSS 以消除列表中项目高度的限制,然后更新
function refreshTodoItems() {
$('#summary').html("Loading...");
var query = todoItemTable;//.where({ complete: false });
// Execute the query and then generate the array list.
query.read().then(function (todoItems) {
var listItems = $.map(todoItems, function (item) {
var listItem = $('<li>')
.attr('data-todoitem-id', item.id)
.append($('<button class="item-delete">Delete</button>'))
.append($('<input type="checkbox" class="item-complete">').prop('checked', item.complete))
.append($('<div>').append($('<input class="item-text">').val(item.text)));
// Only add the image if the URL exists.
if (item.imageUri)
{
listItem.append($('<img>').attr('src', item.imageUri));
}
return listItem;
});
$('#todo-items').empty().append(listItems).toggle(listItems.length > 0);
$('#summary').html('<strong>' + todoItems.length + '</strong> item(s)');
var width = $('#todo-items').width();
$('#todo-items img').css({
'max-width': width, 'height': 'auto'
});
}, handleError);
}
关于cordova - 适用于 Apache Cordova 应用程序的 Azure Blob 存储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25466289/