利用Blob进行文件上传的完整步骤

BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器。下面这篇文章主要给大家介绍了关于利用Blob进行文件上传的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

转载地址:https://www.jb51.net/article/144934.htm

Blob

Blob,Binary Large Object的缩写,二进制类型的大对象,代表不可改变的原始数据

在计算机中,BLOB常常是数据库中用来存储二进制文件的字段类型。

Blob基本用法

Blob对象

Blob对象指的是字节序列,并且具有size属性,是字节序列中的字节总数,和一个type属性,它是小写的ASCII编码的字符串表示的媒体类型字节序列。

size:以字节数返回字节序列的大小。获取时,符合要求的用户代理必须返回一个FileReader或一个FileReaderSync对象可以读取的总字节数,如果Blob没有要读取的字节,则返回0 。
type:小写的ASCII编码字符串表示媒体类型Blob。在获取时,用户代理必须Blob以小写形式返回a类型的ASCII编码字符串,这样当它转换为字节序列时,它是可解析的MIME类型,或者是空字符串(0字节)如果是类型无法确定。

构造函数

创建blob对象本质上和创建一个其他对象的方式是一样的,都是使用Blob() 的构造函数来进行创建。 构造函数接受两个参数:

第一个参数为一个数据序列,格式可以是ArrayBuffer, ArrayBufferView, Blob, DOMString 
第二个参数是一个包含以下两个属性的对象

  • type: MIME的类型,
  • endings: 决定第一个参数的数据格式。默认值为"transparent",用于指定包含行结束符n的字符串如何被写入。 它是以下两个值中的一个: "native",表示行结束符会被更改为适合宿主操作系统文件系统的换行符; "transparent",表示会保持blob中保存的结束符不变。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

var data1 = "a";

var blob1 = new Blob([data1]);

console.log(blob1); //输出:Blob {size: 1, type: ""}

 

var debug = {hello: "world"};

var blob = new Blob([JSON.stringify(debug, null, 2)],{type : 'application/json'});

console.log(blob) // 输出 Blob(22) {size: 22, type: "application/json"}

 

// 创建一个8字节的ArrayBuffer,在其上创建一个每个数组元素为2字节的“视图”

var abf = new ArrayBuffer(8)

var abv = new Int16Array(abf)

var bolb_ArrayBuffer = new Blob(abv, {type : 'text/plain'})

console.log(bolb_ArrayBuffer) //输出 Blob(4) {size: 4, type: "text/plain"}

slice方法

Blob对象有一个slice方法,返回一个新的 Blob对象,包含了源 Blob对象中指定范围内的数据。

?

1

slice(start, end, contentType)

start: 可选,代表 Blob 里的下标,表示第一个会被会被拷贝进新的 Blob 的字节的起始位置。如果传入的是一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。
end: 可选,代表的是 Blob 的一个下标,这个下标-1的对应的字节将会是被拷贝进新的Blob 的最后一个字节。如果你传入了一个负数,那么这个偏移量将会从数据的末尾从后到前开始计算。
contentType: 可选,给新的 Blob 赋予一个新的文档类型。这将会把它的 type 属性设为被传入的值。它的默认值是一个空的字符串。

?

1

2

3

4

5

6

var data = "abcdef";

var blob1 = new Blob([data]);

var blob2 = blob1.slice(0,3);

 

console.log(blob1); //输出:Blob {size: 6, type: ""}

console.log(blob2); //输出:Blob {size: 3, type: ""}

slice用于文件分片上传

  • 分片与并发结合,将一个大文件分割成多块,并发上传,极大地提高大文件的上传速度。
  • 当网络问题导致传输错误时,只需要重传出错分片,而不是整个文件。另外分片传输能够更加实时的跟踪上传进度。

分片上传逻辑如下:

获取要上传文件的File对象,根据chunk(每片大小)对文件进行分片
通过post方法轮循上传每片文件,其中url中拼接querystring用于描述当前上传的文件信息;post body中存放本次要上传的二进制数据片段
接口每次返回offset,用于执行下次上传

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

initUpload();

 

//初始化上传

function initUpload() {

 var chunk = 100 * 1024; //每片大小

 var input = document.getElementById("file"); //input file

 input.onchange = function (e) {

  var file = this.files[0];

  var query = {};

  var chunks = [];

  if (!!file) {

   var start = 0;

   //文件分片

   for (var i = 0; i < Math.ceil(file.size / chunk); i++) {

    var end = start + chunk;

    chunks[i] = file.slice(start , end);

    start = end;

   }

    

   // 采用post方法上传文件

   // url query上拼接以下参数,用于记录上传偏移

   // post body中存放本次要上传的二进制数据

   query = {

    fileSize: file.size,

    dataSize: chunk,

    nextOffset: 0

   }

 

   upload(chunks, query, successPerUpload);

  }

 }

}

 

// 执行上传

function upload(chunks, query, cb) {

 var queryStr = Object.getOwnPropertyNames(query).map(key => {

  return key + "=" + query[key];

 }).join("&");

 var xhr = new XMLHttpRequest();

 xhr.open("POST", "http://xxxx/opload?" + queryStr);

 xhr.overrideMimeType("application/octet-stream");

  

 //获取post body中二进制数据

 var index = Math.floor(query.nextOffset / query.dataSize);

 getFileBinary(chunks[index], function (binary) {

  if (xhr.sendAsBinary) {

   xhr.sendAsBinary(binary);

  } else {

   xhr.send(binary);

  }

 

 });

 

 xhr.onreadystatechange = function (e) {

  if (xhr.readyState === 4) {

   if (xhr.status === 200) {

    var resp = JSON.parse(xhr.responseText);

    // 接口返回nextoffset

    // resp = {

    //  isFinish:false,

    //  offset:100*1024

    // }

    if (typeof cb === "function") {

     cb.call(this, resp, chunks, query)

    }

   }

  }

 }

}

 

// 每片上传成功后执行

function successPerUpload(resp, chunks, query) {

 if (resp.isFinish === true) {

  alert("上传成功");

 } else {

  //未上传完毕

  query.offset = resp.offset;

  upload(chunks, query, successPerUpload);

 }

}

 

// 获取文件二进制数据

function getFileBinary(file, cb) {

 var reader = new FileReader();

 reader.readAsArrayBuffer(file);

 reader.onload = function (e) {

  if (typeof cb === "function") {

   cb.call(this, this.result);

  }

 }

}

Blob URL

blob协议的url使用时就像平时使用的url一样,可以作为图片请求地址,也可以作为文件请求地址。格式:

blob:http://XXX

  • URL.createObjectURL(blob) 创建链接
  • URL.revokeObjectURL(url)

下面是一个下载文件的示例,直接调用即可实现文件下载

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

// file是要下载的文件(blob对象)

downloadHandler: function (file, fileName) {

 let link = document.createElement('a')

 link.href = window.URL.createObjectURL(file)

 link.download = fileName

 link.click()

 window.URL.revokeObjectURL(link.href)

 if (navigator.userAgent.indexOf('Firefox') > -1) {

 const a = document.createElement('a')

 a.addEventListener('click', function (e) {

  a.download = fileName

  a.href = URL.createObjectURL(file)

 })

 let e = document.createEvent('MouseEvents')

 e.initEvent('click', false, false)

 a.dispatchEvent(e)

 }

}

在从后台获取的数据接口中把返回类型设置为blob

?

1

2

var x = new XMLHttpRequest();

x.responseType = 'blob'// 返回一个blob对象

Blob URL和Data URL的区别

Blob URL

Data URL

  • Blob URL的长度一般比较短,但Data URL因为直接存储图片base64编码后的数据,往往很长,如上图所示,浏览器在显示Data URL时使用了省略号(…)。当显式大图片时,使用Blob URL能获取更好的可能性。
  • Blob URL可以方便的使用XMLHttpRequest获取源数据,比如设置XMLHttpRequest返回的数据类型为blob
  • Blob URL 只能在当前应用内部使用,把Blob URL复制到浏览器的地址栏中,是无法获取数据的。Data URL相比之下,就有很好的移植性,可以在任意浏览器中使用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值