【前端实用技巧】将网络图片下载后上传到第三方网站

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第2天,点击查看活动详情

【前端实用技巧】将网络图片下载后上传到第三方网站

引言

内容速递:看了本文您能了解到的知识

下载图片&上传图片

说明

在写技术文档的时候,我们写的MD文档大多都是用的自己的OSS。但是在发布文章的时候会发现,图片会上传到对应的平台上面,而并非是原来的MD文档图片地址,那么,这一步是如何实现的呢?

1、通过图片链接下载图片

在网页上,我们很容易获取到图片的下载地址,具体如何获取,在这里就不具体展开了。

通过XMLHttpRequest下载,这里下载使用Blob格式

const downloadImg = (url) => {
  return new Promise((resolve, reject) => {
    // 创建请求
    const xhr = new XMLHttpRequest()
    xhr.open('get', url, true)
    // 响应类型设置为blob
    xhr.responseType = 'blob'
    xhr.onload = function () {
      if (this.status === 200) {
        resolve(this.response)
      }
    }
    xhr.onerror = reject
    xhr.send()
  })
}
复制代码

Blob 是什么?

Blob(Binary Large Object)表示二进制类型的大对象。在数据库管理系统中,将二进制数据存储为一个单一个体的集合。

Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

测试一下

这里我使用网上的一张图片,可以看看返回的是啥

<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head><body></body>
<script>
  const url = 'https://img1.baidu.com/it/u=1966616150,2146512490&fm=253&fmt=auto&app=138&f=JPEG?w=751&h=500'
  const downloadImg = (url) => {
    return new Promise((resolve, reject) => {
      // 创建请求
      const xhr = new XMLHttpRequest()
      xhr.open('get', url, true)
      // 响应类型设置为blob
      xhr.responseType = 'blob'
      xhr.onload = function () {
        if (this.status === 200) {
          resolve(this.response)
        }
      }
      xhr.onerror = reject
      xhr.send()
    })
  }
  downloadImg(url).then((res) => {
    console.log(res)
  })
</script></html>
复制代码

打印的内容:

image-20220803204627082

可以看到已经成功下载到图片的Blob了

2、文件格式转化

2.1、将Blob转化为File

我们也可以将Blob对象转为File对象

// 将Blob对象转为File对象
const blobToFile = (blob, fileName) => {
  return new window.File([blob], fileName, { type: blob.type })
}
复制代码

测试一下:

<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head><body></body>
<script>
​
  // 测试地址
  const url = 'https://img1.baidu.com/it/u=1966616150,2146512490&fm=253&fmt=auto&app=138&f=JPEG?w=751&h=500'
  
  // 下载图片
  const downloadImg = (url) => {
    return new Promise((resolve, reject) => {
      // 创建请求
      const xhr = new XMLHttpRequest()
      xhr.open('get', url, true)
      // 响应类型设置为blob
      xhr.responseType = 'blob'
      xhr.onload = function () {
        if (this.status === 200) {
          resolve(this.response)
        }
      }
      xhr.onerror = reject
      xhr.send()
    })
  }
​
  // 将Blob对象转为File对象
  const blobToFile = (blob, fileName) => {
    return new window.File([blob], fileName, { type: blob.type })
  }
​
  // 测试
  downloadImg(url).then((res) => {
    // 获取文件名
    const urlArr = url.split('/')
    const fileName = urlArr[urlArr.length - 1]
​
    console.log('Blob对象:', res)
    const file = blobToFile(res, fileName)
​
    console.log('File对象:', file)
​
    return file
  })
</script></html>
复制代码

打印的内容:

image-20220803205707428

2.2、将Blob转为FormData

很多上传图片的,基本都是使用的FormData格式

// 将Blob对象转为FormData对象
const blobToFormData = (blob, fileName) => {
  const formData = new FormData()
  formData.append('file', blob, fileName)
  return formData
}
复制代码

测试一下:

<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head><body></body>
<script>
​
  // 测试地址
  const url = 'https://img1.baidu.com/it/u=1966616150,2146512490&fm=253&fmt=auto&app=138&f=JPEG?w=751&h=500'
  
  // 下载图片
  const downloadImg = (url) => {
    return new Promise((resolve, reject) => {
      // 创建请求
      const xhr = new XMLHttpRequest()
      xhr.open('get', url, true)
      // 响应类型设置为blob
      xhr.responseType = 'blob'
      xhr.onload = function () {
        if (this.status === 200) {
          resolve(this.response)
        }
      }
      xhr.onerror = reject
      xhr.send()
    })
  }
​
  // 将Blob对象转为File对象
  const blobToFile = (blob, fileName) => {
    return new window.File([blob], fileName, { type: blob.type })
  }
​
  // 将Blob对象转为FormData对象
  const blobToFormData = (blob, fileName) => {
    const formData = new FormData()
    formData.append('file', blob, fileName)
    return formData
  }
​
  // 测试
  downloadImg(url).then((res) => {
    // 获取文件名
    const urlArr = url.split('/')
    const fileName = urlArr[urlArr.length - 1]
    console.log('Blob对象:', res)
​
    const file = blobToFile(res, fileName)
    console.log('File对象:', file)
​
    const formData = blobToFormData(file, fileName)
    console.log('FormData对象:', formData)
​
    return file
  })
</script></html>
复制代码

打印内容:

image-20220803223646187

然后发现打印出来的是一个空的对象,看不到效果,需要将其中的属性遍历出来

for (var key of formData.entries()) {
  console.log(key[0] + ', ' + key[1]);
}
复制代码

再次打印就可以看到效果了

image-20220803224037763

3、上传图片

上传图片涉及到隐私,就没有实际演示了

3.1、上传到个人网站

上传到个人网站一般使用的是FormData的文件格式,使用的方式也有许多种

使用XMLHttpRequest

// 上传图片
const uploadImg = (formData) => {
  const url = "upload_url"
  let xhr = new XMLHttpRequest()
  xhr.onload = function () {
    console.log("上传成功")
  };
  xhr.onerror = function () {
    console.log("上传失败")
  };
  xhr.open("post", url, true)
  xhr.send(formData)
};
复制代码

使用Ajax

// 上传图片
const uploadImage = (formData) => {
  const url = "upload_url";
  $.ajax({
    url,
    type: "POST",
    data: formData,
    async: false,
    cache: false,
    contentType: false,
    processData: false,
    success: function (res) {
      console.log("上传成功", res);
    },
    error: function (res) {
      console.log("上传失败", res);
    },
  });
}
复制代码

使用axios

这个一般在Vue中使用比较多

// 上传图片
const uploadImage = (formData) => {
  const url = "upload_url";
  axios.post(url, formData)
}
复制代码

3.2、上传到OSS

能够上传的OSS,当然也可以上传到其他对象存储服务,可以参考OSS的案例。

OSS上传,可直接上传File对象

import OSS from "ali-oss";
​
// 上传到OSS
export const uploadImageToOSS = async (
  fileName: string,
  file: File,
  accessKeyId: string,
  accessKeySecret: string,
  ...props
) => {
  let client = new OSS({
    endpoint,
    bucket,
    accessKeyId,
    accessKeySecret,
    internal: true,
    ...props,
  });
  const res = await client.put(fileName, file);
  if (res.status === 200) {
    return { url: res.url };
  }
  throw new Error('上传失败');
};
复制代码

总结

上传图片的场景,大部分可能用在表单上传图片、搭建自己的博客系统、配置富文本编辑器、MD文档编辑器等等。用的场景还是比较丰富。

博客说明与致谢

文章所涉及的部分资料来自互联网整理,其中包含自己个人的总结和看法,分享的目的在于共建社区和巩固自己。

引用的资料如有侵权,请联系本人删除!

感谢万能的网络,W3C,菜鸟教程等!

感谢勤劳的自己个人博客GitHub学习GitHub

公众号【归子莫】,小程序【子莫说】

如果你感觉对你有帮助的话,不妨给我点赞鼓励一下,好文记得收藏哟!关注我一起成长!

幸好我在,感谢你来!

猜你喜欢

转载自juejin.im/post/7127672575768920094