vue上傳圖片到七牛雲的思路與實現

本文分爲思路篇和代碼篇,思路篇主要是思路和代碼混合,主要重點是講解思路;代碼篇是註釋和代碼結合,主要展現代碼.html

1、思路篇

方法一:上傳圖片流程的思路(經過前臺上傳圖片):

1.接收token前的操做前端

說明:前臺點擊上傳圖片的按鈕前,須要先獲取七牛雲的token,須要的流程以下:node

1.1前臺打開本地圖片的時候,須要獲取本地圖片的名稱(用來賦值給下面的key,以便生成token),而後發給後臺,後臺把文件名稱(此時文件名建議進行操做,重命名)賦值給keyios

1.2後臺根據:key以及你的七牛雲命名空間的名稱即:bucket 生成token 後發送給前臺

2.接受到token後的操做json

2.1前臺接收到token,須要把文件轉爲字節流 而後把【token】以及【文件字節流】以及【文件名稱:key】打包成一個對象,而後開始發送到七牛雲axios

3.具體代碼:後臺操做後端

//須要填寫你的 Access Key 和 Secret Key 這個在七牛雲 我的中心>密鑰管理 功能裏面
qiniu.conf.ACCESS_KEY = '0kSEeVVtcqWFQ18z0TWlDe6eBC3lFchpHLBNe-_F';//公鑰
qiniu.conf.SECRET_KEY = 'Y2P5am6LWW44yxo2YWwsiY4RteqyFeut58gCHBM_';//私鑰
//要上傳的空間
bucket = 'we-teach';//個人bucket名稱,即文件的命名空間的名稱
//上傳到七牛後保存的文件名
key = 'my-nodejs-logo.png';//此處我直接在前臺生成我須要保持的文件名,而後發到給後端。也能夠把文件名直接發到後端,讓後端處理,因爲前端後端都是我一我的寫的,因此我比較隨意
//構建上傳策略函數,生成token並設置回調的url以及須要回調給業務服務器的數據。此處的回調服務器地址須要你的公網服務器地址,可是我直接在本地操做的,沒有公網地址,因此就沒有改動七牛雲的example了,直接copy
function uptoken(bucket, key) {
  var putPolicy = new qiniu.rs.PutPolicy(bucket+":"+key);
  putPolicy.callbackUrl = 'http://your.domain.com/callback';
  putPolicy.callbackBody = 'filename=$(fname)&filesize=$(fsize)';
  return putPolicy.token();
}
//生成上傳 Token
token = uptoken(bucket, key);//此處的token須要發給前臺,好讓前臺開始操做,實現圖片上傳
console.log("七牛雲上傳圖片的token:",token);//後臺代碼結束

前臺操做瀏覽器

//1.選中圖片時發送key,即文件名稱給後臺,以便後臺生成token
this.axios.get('/filename','my-nodejs-logo.png')
//filePath_or_stream是要上傳文件的本地路徑或者字節流,雖然七牛雲官方文檔有說最簡單//的上傳就是本地上傳時給一個本地的路徑就行了
//可是我以爲直接指定本地的圖片路徑只適合後臺上傳,不適合前臺,具體緣由見下面的後話
//因此本文演示的都是傳所有文件數據,而非文件地址
// filePath_or_stream = './nodejs-logo.png'||filePath_or_stream=readableStream【readableStream是前臺傳過來的所有文件的數據流】
filePath_or_stream = readableStream;//圖片的字節流數據
//2.選中圖片後,開始上傳前:獲取token
this.axios.get('/up/token').then(res => {
  console.log(res)
  const formdata = new FormData()//FormData是瀏覽器的方法,用於html追加表單鍵值對,詳細使用能夠看看MDN文檔,簡單介紹看看下面後話個人介紹
  formdata.append('file', req.file)//往表單上傳的數據域追加file屬性,它的value是req.file。 reqreq.file是咱們本地的文件地址,elementui的el-upload裏的http-request像咱們本地計算機發起請求數據,會把咱們選擇的文件地址賦值給req.file(原生的html的表單上傳屬性也能夠獲取文件的地址)
  formdata.append('token', res.data)//往表單上傳的數據域追加token屬性,它的value是res.data,res.data是後臺在咱們請求token時發送過來的數據
  formdata.append('key', keyname)//往表單上傳的數據域追加key屬性, keyname是咱們自定義須要保存的文件名稱
  // 3.點擊上傳時:獲取到憑證以後再將文件上傳到七牛雲空間
  //this.domain是你要上傳的七牛雲的空間所綁定的域名,formdata包含上傳的全部數據,config用來設置請求頭
  this.axios.post(this.domain, formdata, config).then(res => {
    this.imageUrl = 'http://' + this.qiniuaddr + '/' + res.data.key
    // console.log(this.imageUrl)
  })
})

方法二:上傳圖片流程的思路(經過後臺上傳圖片):

1.接收token前的操做
說明:前臺點擊上傳圖片的按鈕時,【須要先把本地圖片的名稱以及圖片字節流數據發給後臺】,【或者把修改好後的須要重命名的圖片名稱以及圖片字節流數據發給後臺】,須要的流程以下:
1.1前臺上傳本地圖片的時候,須要獲取本地圖片的名稱(用來賦值給下面的key,以便生成token),而後同時把圖片字節流一併發給後臺,後臺把文件名(此時文件名建議進行操做,重命名)稱賦值給key
1.2後臺根據:key以及你的七牛雲命名空間的名稱即:bucket 生成token 服務器

2.接受到token後的操做
2.1後臺生成token後, 把【token】以及【文件字節流】以及【文件名稱:key】打包成一個對象,而後開始發送到七牛雲併發

3.具體代碼:後臺操做

//須要填寫你的 Access Key 和 Secret Key 這個在七牛雲 我的中心>密鑰管理 功能裏面
qiniu.conf.ACCESS_KEY = '0kSEeVVtcqWFQ18z0TWlDe6eBC3lFchpHLBNe-_F';//公鑰
qiniu.conf.SECRET_KEY = 'Y2P5am6LWW44yxo2YWwsiY4RteqyFeut58gCHBM_';//私鑰

//要上傳的空間
bucket = 'we-teach';//個人bucket名稱,即文件的命名空間的名稱

//上傳到七牛後保存的文件名
key = 'my-nodejs-logo.png';//此處我直接在前臺生成我須要保持的文件名,而後發到給後端。也能夠把文件名直接發到後端,讓後端處理,因爲前端後端都是我一我的寫的,因此我比較隨意
//構建上傳策略函數,生成token並設置回調的url以及須要回調給業務服務器的數據。此處的回調服務器地址須要你的公網服務器地址,//可是我直接在本地操做的,沒有公網地址,因此就沒有改動七牛雲的example了,直接copy沒改function uptoken(bucket, key) {
  var putPolicy = new qiniu.rs.PutPolicy(bucket+":"+key);
  putPolicy.callbackUrl = 'http://your.domain.com/callback';
  putPolicy.callbackBody = 'filename=$(fname)&filesize=$(fsize)';
  return putPolicy.token();
}

//生成上傳 Token
token = uptoken(bucket, key);//此處的token須要根據【前臺發送來的圖片名稱】即:【key】加上【bucket】生成
console.log("七牛雲上傳圖片的token:",token);

//filePath_or_stream是要上傳文件的本地路徑或者字節流,雖然七牛雲官方文檔有說最簡單//的上傳就是本地上傳時給一個本地的路徑就行了
//可是我以爲直接指定本地的圖片路徑只適合後臺上傳,不適合前臺,具體緣由見下面的後話
//因此本文演示的都是傳所有文件數據,而非文件地址
// filePath_or_stream = './nodejs-logo.png'||filePath_or_stream=readableStream【readableStream是前臺傳過來的所有文件的數據流】
filePath_or_stream = readableStream;//使用前臺傳過來的字節流數據進行賦值
//構造上傳函數 uptoken:上傳憑證,由bucket與咱們傳過來的【key即須要保存的文件的名稱】生成。 key【key即須要保存的文件的名稱】, //localFile【本地文件,能夠是數據流或者地址,本文都是採用數據流】
function uploadFile(uptoken, key, localFile) {
  var extra = new qiniu.io.PutExtra();
    qiniu.io.putFile(uptoken, key, localFile, extra, function(err, ret) {
      if(!err) {
        // 上傳成功, 處理返回值
        console.log(ret.hash, ret.key, ret.persistentId);       
      } else {
        // 上傳失敗, 處理返回代碼
        console.log(err);
      }
  });
}
//調用uploadFile上傳
uploadFile(token, key, filePath_or_stream);

前臺操做不寫,思路篇思路介紹爲主。

2、代碼篇

待追加……

3、後話

1.關於filePath_or_stream

雖然七牛雲容許咱們在上傳的時候直接在上傳本地圖片的地址就行了,可是我以爲此種場景只適合後臺上傳,而且後臺上傳還仍然有所限制,爲何呢?

下面解釋: 因爲咱們上傳數據的時候並非無緣無故就能夠上傳的,須要點對點的傳數據。

1.1情景模擬:

(A發送數據給B,只發送了數據的地址,就至關於咱們只發送了圖片地址) 假設A發送數據給B,那麼A就必定要把數據拿到手,才能發送給B,雖然這裏有講廢話的嫌疑,可是的確有道理。

假設咱們上傳圖片時前臺直接發送咱們圖片的地址給七牛雲,那麼七牛雲只接收到咱們本地計算機的地址,如:localhost://we-teach/1.png 那麼七牛雲雖然知道咱們須要上傳的圖片的地址,可是卻無能爲力,首先咱們的本地計算機的ip地址不是公網地址,七牛雲即便知道咱們本地的文件存儲地址,也沒法從咱們的計算機獲取數據 那麼若是是後臺發送的話,須要後臺部署在一個公網IP的服務器上面,此時發送地址給七牛雲,那麼他接收到請求後就能夠從咱們的服務器拉取數據。 固然這些只是我猜想的,由於具體技術我也不太清楚,仍是小菜雞一個。

1.2情景模擬:

(A發送數據給B,發送了數據的所有信息,就至關於咱們把圖片所有發送過去了) 因此我以爲既然只傳地址的原理我搞不太懂,那麼把數據所有發過去就能夠了,這個原理簡單且易懂,A拿着數據所有送到B門口,那麼B就確定能拿到了。因此本文傳過去的數據都是圖片的所有信息,而非本地地址而已。

1.3前臺只傳本地地址的狀況下,能不能讓七牛雲也知道咱們發送圖片的具體信息?

這個能夠用FormData對象,這個是瀏覽器的接口,原生js沒有,就是說這個方法只能用於html網頁 formData,就像他的名字同樣,表單數據,它能夠用來給表單數據追加鍵值對。

具體用法能夠看看MDN文檔:https://developer.mozilla.org...

FormData 是一個構造函數,使用它須要new一個實例const formdata = new FormData(),而後把咱們本地的圖片地址傳入進去:formdata.append('file', req.file),那麼表單數據對象就多了一個file的屬性,他的值就是req.file。
不管是使用elementUi的上傳組件,仍是原生的html的上傳的元素,道理都同樣可使用formData。

其實formData並非只傳地址就能夠實現圖片上傳,當它append追加的是一個表單對象是,它會自動注入該表單對象的所有數據。好比formdata.append('file', req.file),它會把req.file的所有數據,即圖片數據所有注入給屬性名爲file的值。因此formData本質就是注入某個表單對象的所有數據,這個說到底也不是傳本地文件地址,而是把本地文件的所有數據流注入到表單裏面。
小demo:

<template>
  <!-- upload -->
  <div class="upload">
    <el-upload
      class="avatar-uploader"
      :action= domain
      :http-request = upqiniu
      :show-file-list="false"
      :before-upload="beforeUpload">
      <img v-if="imageUrl" :src="imageUrl" class="avatar">
      <i v-else class="el-icon-plus avatar-uploader-icon"></i>
    </el-upload>
  </div>
</template>
<script>
export default {
  data () {
    return {
      imageUrl: '',
      token: {},
      // 七牛雲的上傳地址,根據本身所在地區選擇,我這裏是華南區
      domain: 'https://upload-z2.qiniup.com',
      // 這是七牛雲空間的外鏈默認域名
      qiniuaddr: 'p3z6q1uw1.bkt.clouddn.com'
    }
  },
  methods: {
    // 上傳文件到七牛雲
    upqiniu (req) {
      console.log(req)
      const config = {
        headers: {'Content-Type': 'multipart/form-data'}
      }
      let filetype = ''
      if (req.file.type === 'image/png') {
        filetype = 'png'
      } else {
        filetype = 'jpg'
      }
      // 重命名要上傳的文件
      const keyname = 'lytton' + new Date() + Math.floor(Math.random() * 100) + '.' + filetype
      // 從後端獲取上傳憑證token
      this.axios.get('/up/token').then(res => {
        console.log(res)
        const formdata = new FormData()
        formdata.append('file', req.file)//追加file數據,req.file是咱們本地的文件地址,elementui的el-upload裏的http-request像咱們本地計算機發起請求數據,會把咱們選擇的文件地址賦值給req.file
        formdata.append('token', res.data)
        formdata.append('key', keyname)
        // 獲取到憑證以後再將文件上傳到七牛雲空間
        this.axios.post(this.domain, formdata, config).then(res => {
          this.imageUrl = 'http://' + this.qiniuaddr + '/' + res.data.key
          // console.log(this.imageUrl)
        })
      })
    },
    // 驗證文件合法性
    beforeUpload (file) {
      const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
      const isLt2M = file.size / 1024 / 1024 < 2
      if (!isJPG) {
        this.$message.error('上傳頭像圖片只能是 JPG 格式!')
      }
      if (!isLt2M) {
        this.$message.error('上傳頭像圖片大小不能超過 2MB!')
      }
      return isJPG && isLt2M
    }
  }
}
</script>
<style scoped>
.upload {
  width: 600px;
  margin: 0 auto;
}
.avatar-uploader .el-upload {
  border: 5px dashed #ca1717 !important;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409EFF;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

2.關於qiniu.io.PutExtra()

var extra = new qiniu.io.PutExtra();//extra官方文檔雖然沒有明確說明,

可是有一個example,我估計它是用來設置參數的可選值 例子:

我的以爲設置了擴展參數,而後執行回調操做時,它會在七牛雲本來返回的原始json數據響應上面加上咱們自定義的參數。

var putExtra = new qiniu.resume_up.PutExtra(); // 擴展參數

putExtra.params = { "x:name": "", "x:age": 27, }

putExtra.fname = 'testfile.mp4';

相關文章
相關標籤/搜索