图片上传姿势以及你不知道的Typed Arrays

在思否答题遇到几个关于图片上传的问题,中间都涉及到ArrayBuffer的概念,心心念念想整理下这方面的知识,也希望让更多人能有所收获。

各位看官,一起开始吧。

1. 如何上传文件

前端中上传一般使用FormData创建请求数据,示例如下:

var formData = new FormData();

formData.append("username", "Groucho");

// HTML 文件类型input,由用户选择
formData.append("userfile", fileInputElement.files[0]);

// JavaScript file-like 对象
var content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的正文...
var blob = new Blob([content], { type: "text/xml"});

formData.append("webmasterfile", blob);

var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php");
request.send(formData);

FormData 对象的字段类型可以是 Blob, File, 或者 string,如果它的字段类型不是Blob也不是File,则会被转换成字符串。

我们通过<input type="input"/>选择图片,把获取到的file放到FormData,再提交到服务器。

如果上传多个文件,就追加到同一个字段中。

fileInputElement.files.forEach(file => {
  formData.append('userfile', file);
})

其中的file-likenew Blob的示例说明我们可以构造一个新的文件直接上传。

场景1:剪辑图片上传

我们通过裁剪库可以得到data url或者canvas

cropperjs举例,使用getCroppedCanvas获取到canvas,然后利用自身的toBlob获取到file数据,再通过FormData上传。

转换的核心代码可以参考下面:

canvas = cropper.getCroppedCanvas({
  width: 160,
  height: 160,
});

initialAvatarURL = avatar.src;
avatar.src = canvas.toDataURL();

// 从canvs获取blob数据
canvas.toBlob(function (blob) {
  var formData = new FormData();
  formData.append('avatar', blob, 'avatar.jpg');

  // 接下来可以发起请求了
  makeRequest(formData)
})

场景2:base64图片上传

获取到base64形式的图片后,我们通过下面函数转为blob形式:

function btof(base64Data, fileName) {
  const dataArr = base64Data.split(",");
  const byteString = atob(dataArr[1]);

  const options = {
    type: "image/jpeg",
    endings: "native"
  };
  const u8Arr = new Uint8Array(byteString.length);
  for (let i = 0; i < byteString.length; i++) {
    u8Arr[i] = byteString.charCodeAt(i);
  }
  return new File([u8Arr], fileName + ".jpg", options);
}

这样我们拿到了文件file,然后就可以继续上传了。

场景3:URL图片上传

想要直接用图片URL上传,我们可以分成两部来做:

  1. 获取base64
  2. 然后转为file

其中关键代码是如何从URL中创建canvas,这里通过创建Image对象,在图片挂载之后,填充到到canvas中。

var img =
  "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=508387608,2848974022&fm=26&gp=0.jpg"; //imgurl 就是你的图片路径

var image = new Image();
image.src = img;
image.setAttribute("crossOrigin", "Anonymous");
image.onload = function() {
  // 第1步:获取base64形式的图片
  var base64 = getBase64Image(image);

  var formData = new FormData(); 

  // 第2步:转换base64到file
  var file = btof(base64, "test");
  formData.append("imageName", file);
};

function getBase64Image(img) {
  var canvas = document.createElement("canvas");
  canvas.width = img.width;
  canvas.height = img.height;
  var ctx = canvas.getContext("2d");
  ctx.drawImage(img, 0, 0, img.width, img.height);
  var ext = img.src.substring(img.src.lastIndexOf(".") + 1).toLowerCase();
  var dataURL = canvas.toDataURL("image/" + ext);

  return dataURL;
}

See the Pen [url image转为base64](https://codepen.io/ineo6/pen/MWgpGQZ) by neo ([@ineo6](https://codepen.io/ineo6)) on [CodePen](https://codepen.io).

原文链接:segmentfault.com

上一篇:阮一峰ES6全面回顾
下一篇:Vue中生命周期的理解

相关推荐

官方社区

扫码加入 JavaScript 社区