Base64 转 File

1. Base64转Blob

  1. function base64ToBlob (datastr) {
  2. let arr = datastr.split(','),
  3. mime = arr[0].match(/:(.*?);/)[1],
  4. bstr = atob(arr[1]),
  5. n = bstr.length,
  6. u8arr = new Uint8Array(n);
  7. while(n--) {
  8. u8arr[n] = bstr.charCodeAt(n)
  9. }
  10. return new Blob([u8arr], {type: mime})
  11. }

2. Blob转File

  1. function blobToFile(blob) {
  2. blob.lastModified = Date.now()
  3. blob.lastModifiedDate = new Date()
  4. return blob
  5. }

3. 利用new FormData() 给文件命名

  1. let formdata = new FormData()
  2. formdata.append('file', blob, '自定义文件.后缀')

💡TIP

  1. 由于浏览器兼容问题,没有使用 new File()
  2. 尽管给 blob 对象添加修改时间和命名,但是最后得到的文件并不是真正意义上的 file, 传递至后台,后台接收到的文件名会是 'blob',而不是我们自定义的 name,可利用 new FormData() 的第三个参数解决

文件校验

校验类型

  1. function fileTypeCheck (file, accept = []) {
  2. return new Promise((resolve, reject) => {
  3. let name = file.name,
  4. type = name.slice(name.lastIndexOf('.')) || 'unknown';
  5. if (accept.includes(type)) {
  6. resolve(true)
  7. } else {
  8. reject(false)
  9. }
  10. })
  11. }

校验大小

  1. function fileSizeCheck(file, limit = 10) {
  2. return new Promise((resolve, reject) => {
  3. const { size } = file
  4. if (Number(size / (1024 * 1024).toFixed(2)) > limit) {
  5. reject(false)
  6. } else {
  7. resolve(true)
  8. }
  9. })
  10. }

上传文件 Network Error

用户上传文件至浏览器,然后在本地修改或删除该文件,后续没有重新上传而是使用浏览器保存的那份旧文件,上传会失败;此时捕获到的 axios 的错误提示 Network Error,然后在浏览器控制台可以看到接口的错误信息中提示:ERR_UPLOAD_FILE_CHANGE 或者 ERR_FILE_NOT_FOUND
由于我在 axios 的响应拦截器中设置了若捕获到 Network Error,会提示 网络错误 ,这样的提示对用户不太友好;通过查询资料可以发现,前端其实可以判断文件是否被删除或修改的,这样,若用户无意中触发了上述操作,我们就能在上传之前给出对应提示;

  1. function isFileModifyOrDelete(file) {
  2. return new Promise((resolve, reject) => {
  3. const ERROR_DICT = {
  4. 'NotFoundError': '找不到本地源文件',
  5. 'NotReadableError': '本地源文件已修改',
  6. 'SecurityError': '操作安全错误'
  7. }
  8. const reader = new FileReader()
  9. reader.readAsArrayBuffer(file)
  10. reader.onload = function () {
  11. return resolve(true)
  12. }
  13. reader.onerror = function (e) {
  14. let error = e.target.error
  15. return reject(ERROR_DICT[error.name])
  16. }
  17. })
  18. }

参考:

  1. File 相关的异常
  2. FileReader 读取文件
  3. stackoverflow

文件切片、断点续传