Javascript 上传文件到Azure存储
对一些前端工程师来讲,使用javascript上传文件到Azure存储中可能是需要掌握的技能,希望这篇博客能给到帮助。
在开始前我们需要了解以下几点:
共享访问签名(Shared Access Signature(SAS)
共享访问签名
共享访问签名,是用于提供对Windows Azure Storage中的Container,Blob,Table以及Queue在特定时间范围内进行有限权限访问的URL。通常情况下,我们访问Azure存储都是以账户名和密码的方式来实现的,通过这种方式也给使用者包括增删改在内的最大的访问权限,但是在实际情况中,我们可能希望用户只有读的权限,同时我们也不希望将账户名和密码泄露出去,共享访问签名很好的解决了这类问题。我们在使用Javascript上传时就是通过共享访问签名的URL来进行的。
Azure 存储服务的跨域资源共享 (CORS) 支持
大概在2014年3月份的时候Azure已经支持CORS,经过测试目前中国版和国际版都已经支持,我们在使用Javascript上传的时候是将资源以PUT的方式上传到类似于http://***.blob.core.chinacloudapi.cn这样域名的地方,这就涉及到CORS的问题,在默认情况下Azure存储是禁用CORS的,所以我们需要使用版本 2013-08-15 或更高版本设置适当的服务属性,并向服务属性中添加 CORS 规则,如果我们没有启用CORS规则,我们可能会得到403错误,使用Fiddler工具会得到更详细的错误信息:”CORS not enabled or no matching rule found for this request”。
通过上面的描述,我们在开始编程前,我们需要SAS URL,还需要为我们的blob配置CORS规则,这些我们可以通过Azure SDK来实现,关于这部分我就不介绍了,详细请阅读:#SAS:http://www.windowsazure.cn/zh-cn/documentation/articles/storage-dotnet-shared-access-signature-part-2/
如果我们不太了解C#,我们可以借助Azure Storage Explorer来进行配置,下面我介绍下简单的配置:
1) 得到SAS URL

打开Azure Storage Explorer点击“Security”,选择SAS失效的时间,并选择赋予相应的权限,如上图高亮标注的部分。
2) 配置CORS规则

打开Azure Storage Explorer鼠标停留在”Blob Containers”,这时会出现CORS设置按钮,点击新增CORS规则,并如上图设置,关于具体的设置信息,请阅读:https://msdn.microsoft.com/zh-cn/library/azure/dn535601.aspx?f=255&MSPPError=-2147217396,图中的设置是我测试的字段,可作为参考。
下面是具体的代码
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>File Uploader</title>
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script>
var maxBlockSize = 256 * 1024;//Each file will be split in 256 KB.
var numberOfBlocks = 1;
var selectedFile = null;
var currentFilePointer = 0;
var totalBytesRemaining = 0;
var blockIds = new Array();
var blockIdPrefix = "block-";
var submitUri = null;
var bytesUploaded = 0;
$(document).ready(function () {
$("#output").hide();
$("#file").bind('change', handleFileSelect);
if (window.File && window.FileReader && window.FileList && window.Blob) {
// Great success! All the File APIs are supported.
} else {
alert('The File APIs are not fully supported in this browser.');
}
});
//Read the file and find out how many blocks we would need to split it.
function handleFileSelect(e) {
maxBlockSize = 256 * 1024;
currentFilePointer = 0;
totalBytesRemaining = 0;
var files = e.target.files;
selectedFile = files[0];
$("#output").show();
$("#fileName").text(selectedFile.name);
$("#fileSize").text(selectedFile.size);
$("#fileType").text(selectedFile.type);
var fileSize = selectedFile.size;
if (fileSize < maxBlockSize) {
maxBlockSize = fileSize;
console.log("max block size = " + maxBlockSize);
}
totalBytesRemaining = fileSize;
if (fileSize % maxBlockSize == 0) {
numberOfBlocks = fileSize / maxBlockSize;
} else {
numberOfBlocks = parseInt(fileSize / maxBlockSize, 10) + 1;
}
console.log("total blocks = " + numberOfBlocks);
var baseUrl = $("#sasUrl").val();
var indexOfQueryStart = baseUrl.indexOf("?");
submitUri = baseUrl.substring(0, indexOfQueryStart) + '/' + selectedFile.name + baseUrl.substring(indexOfQueryStart);
console.log(submitUri);
}
var reader = new FileReader();
reader.onloadend = function (evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
var uri = submitUri + '&comp=block&blockid=' + blockIds[blockIds.length - 1];
var requestData = new Uint8Array(evt.target.result);
$.ajax({
url: uri,
type: "PUT",
data: requestData,
processData: false,
beforeSend: function (xhr) {
xhr.setRequestHeader('x-ms-blob-type', 'BlockBlob');
xhr.setRequestHeader('Content-Length', requestData.length);
},
success: function (data, status) {
console.log(data);
console.log(status);
bytesUploaded += requestData.length;
var percentComplete = ((parseFloat(bytesUploaded) / parseFloat(selectedFile.size)) * 100).toFixed(2);
$("#fileUploadProgress").text(percentComplete + " %");
uploadFileInBlocks();
},
error: function (xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
}
};
function uploadFileInBlocks() {
if (totalBytesRemaining > 0) {
console.log("current file pointer = " + currentFilePointer + " bytes read = " + maxBlockSize);
var fileContent = selectedFile.slice(currentFilePointer, currentFilePointer + maxBlockSize);
var blockId = blockIdPrefix + pad(blockIds.length, 6);
console.log("block id = " + blockId);
blockIds.push(btoa(blockId));
reader.readAsArrayBuffer(fileContent);
currentFilePointer += maxBlockSize;
totalBytesRemaining -= maxBlockSize;
if (totalBytesRemaining < maxBlockSize) {
maxBlockSize = totalBytesRemaining;
}
} else {
commitBlockList();
}
}
function commitBlockList() {
var uri = submitUri + '&comp=blocklist';
console.log(uri);
var requestBody = '<?xml version="1.0" encoding="utf-8"?><BlockList>';
for (var i = 0; i < blockIds.length; i++) {
requestBody += '<Latest>' + blockIds[i] + '</Latest>';
}
requestBody += '</BlockList>';
console.log(requestBody);
$.ajax({
url: uri,
type: "PUT",
data: requestBody,
beforeSend: function (xhr) {
xhr.setRequestHeader('x-ms-blob-content-type', selectedFile.type);
xhr.setRequestHeader('Content-Length', requestBody.length);
},
success: function (data, status) {
console.log(data);
console.log(status);
},
error: function (xhr, desc, err) {
console.log(desc);
console.log(err);
}
});
}
function pad(number, length) {
var str = '' + number;
while (str.length < length) {
str = '0' + str;
}
return str;
}
</script>
</head>
<body>
<form>
<div style="margin-left: 20px;">
<h1>File Uploader</h1>
<p>
<strong>SAS URI</strong>:
<br />
<span class="input-control text">
<input type="text" id="sasUrl" style="width: 50%"
value="" />
</span>
</p>
<p>
<strong>File To Upload</strong>:
<br />
<span class="input-control text">
<input type="file" id="file" name="file" style="width: 50%" />
</span>
</p>
<div id="output">
<strong>File Properties:</strong>
<br />
<p>
Name: <span id="fileName"></span>
</p>
<p>
File Size: <span id="fileSize"></span> bytes.
</p>
<p>
File Type: <span id="fileType"></span>
</p>
<p>
<input type="button" value="Upload File" onclick="uploadFileInBlocks()" />
</p>
<p>
<strong>Progress</strong>: <span id="fileUploadProgress">0.00 %</span>
</p>
</div>
</div>
<div>
</div>
</form>
</body>
</html>
代码主要是将文件切成小块,并使用Put blob操作上传相应的小块,最后使用Put blob list将上传的各个小块组成资源文件。
Javascript 上传文件到Azure存储的更多相关文章
- django 用户上传文件media的存储访问配置1
1. 首先新建文件夹media 后 在项目setting中具体配置: MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media ...
- javascript 上传文件相关 (5) Blob 对象
这一系列文章都讲述的是关于使用 JavaScript 操作文件相关的知识,其中最重要的是 File 对象,而实际上 file 对象只是 blob 对象的一个更具体的版本,blob 存储着大量的二进制数 ...
- 微信小程序云开发-云存储-上传文件(图片/视频)到云存储 精简代码
说明 图片/视频这类文件是从客户端会话选择文件. 一.wxml文件添加if切换显示 <!--上传文件到云存储--> <button bindtap="chooseImg&q ...
- 利用jquery.form实现异步上传文件
实现原理 目前需要在一个页面实现多个地方调用上传控件上传文件,并且必须是异步上传.思考半天,想到通过创建动态表单包裹上传文件域,利用jquery.form实现异步提交表单,从而达到异步上传的目的,在上 ...
- RN 上传文件到以及上传文件到七牛云(初步)
本文将介绍: 如何使用原生 Javascript 上传文件 如何使用七牛云 SDK 上传文件到七牛云 在 App 中文件上传是一个非常重要的需求,但是翻遍 React Naitve 的官方文档没有发现 ...
- 使用XWAF框架(2)——上传文件
XWAF提供了上传文件的HttpFileUploader工具类,具备强大的多文件上传.文件类型过滤.文件大小限制.存储目录设置.文件名称更改等功能,简化了Web应用开发的编程工作. 它能同时解析表单参 ...
- Servlet 表单及上传文件
// 文件路径 D:\ApacheServer\web_java\HelloWorld\src\com\test\TestServletForm.java package com.test; impo ...
- app端上传文件至服务器后台,web端上传文件存储到服务器
1.android前端发送服务器请求 在spring-mvc.xml 将过滤屏蔽(如果不屏蔽 ,文件流为空) <!-- <bean id="multipartResolver&q ...
- c#上传文件并将word pdf转化成txt存储并将内容写入数据库
c#上传文件并将word pdf转化成txt存储并将内容写入数据库 using System; using System.Data; using System.Configuration; using ...
随机推荐
- 每天一个Linux命令 - 【chkconfig】
[命令]:chkonconfig [语法]:chkconfig [选项] [功能介绍]:chkconfig 命令是Redhat兼容的Linux发行版中的系统服务管理工具,它可以查询和更新不同的运行等一 ...
- 11-EasyNetQ之多态发布和订阅
你能够订阅一个接口,然后发布基于这个接口的实现. 让我们看下一个示例.我有一个接口IAnimal和两个实现Cat和Dog: public interface IAnimal { string Name ...
- 电商模式O2O、C2C、B2B、B2C
电商模式O2O.C2C.B2B.B2C o2o o2o 是 online to offline 分为四种运营模式 1.online to offline 是线上交易到线下消费体验 2.offline ...
- JVM中的JIT
JVM中的JIT 介绍Java虚拟机的文章或者书籍总会提到Java虚拟机中的JIT编译器,可是JIT编译器到底是什么?为什么需要JIT编译呢? JIT编译器,是Just In Time编译的意思,又称 ...
- saltstack系列(六)——zmq扩展(二)
问题 我们已经熟练的掌握了REQ/REP模式,它是一个一对多的模式,一个REP对应多个REQ. 但是现实工作中,我们会遇到这样的难题,一个REP无法满足REQ的提问,因为REQ太多了,虽然可以增加一个 ...
- Android4.0+锁屏程序开发——按键屏蔽篇
开发锁屏程序的时候我们要面临的重要问题无疑是如何屏蔽三个按键,Back,Home,Menu 看似简单的功能,实现起来却并不是那么容易. [屏蔽Back按键] 相对来说,屏蔽Back键是比较简单的,只 ...
- codeforce467DIV2——D. Sleepy Game
分析 这个题乍一看有点像之前在CF上做过的一道DP,也是两个人下棋,但是写着写着觉得不对···这个题是的最优策略只是player 1 如果有环则是draw,可以DFS的时候顺便判环(拓扑排序的方法), ...
- ZIP压缩格式与RAR压缩格式
早已习惯了安装系统之后必须安装winrar,压缩文件也已经习惯了rar格式,这种习惯的力量真的挺可怕的.在工作中你的同事可能没有安装winrar,或者他们不喜欢安装盗版软件,这时候你给他们发送过去的是 ...
- win32多线程 (一) 线程创建与结束等待
#include "stdafx.h"#include <Windows.h>#include <iostream> using namespace std ...
- laravel的mvc