七牛云上傳圖片

前言

上傳圖片是很常見的需求咽斧,方法也有很多。本次使用的是七牛云的對象存儲躬存,七牛云的oss做的還是比較出色的收厨。

七牛云的上傳大體分為兩種

  • 向服務端請求七牛的文件上傳 token,然后將文件上傳至七牛(授權(quán)式上傳)
  • 將文件直接上傳到服務端优构,再由服務端將文件傳輸至七牛

授權(quán)式上傳其實還分兩種诵叁,一種是調(diào)用 qiniu SDK,一種直接調(diào)用七牛的上傳接口

本文會把兩種方法都實現(xiàn)钦椭,實際開發(fā)根據(jù)情況選用

使用技術(shù)

formData + axios + koa + koa-body

授權(quán)式上傳

這種上傳方式拧额,后端只需要返回七牛的 token碑诉,由前端調(diào)用 SDK 或者 上傳接口

SDK上傳

七牛云的sdk可以通過script標簽引入

https://unpkg.com/qiniu-js@2.4.0/dist/qiniu.min.js
  • 通過sctipt標簽引入該文件,會在全局生成名為 qiniu 的對象

  • 通過npm安裝

    npm install qiniu-js --save
    
    import * as qiniu from 'qiniu-js'
    

qiniu-sdk

主要api侥锦,qiniu.upload(file, key, token, putExtra, config)

  • file:Blob對象
  • key:文件名
  • token:上傳驗證信息进栽,前端通過接口請求后端獲得
  • config:上傳配置參數(shù)
  • putExtra:額外配置參數(shù)

調(diào)用成功后返回一個observable對象,調(diào)用它的 subscribe 方法獲取到響應結(jié)果

observable.subscribe({
  complete(res) {
    // 上傳完成的響應信息恭垦,res 包含 hash快毛、key兩個屬性(默認)
  },
  next(res) {
    // 接收上傳進度信息,res 包含loaded番挺、total唠帝、percent三個屬性,提供上傳進度信息玄柏。
  },
  error(err) {
    // 上傳錯誤觸發(fā)襟衰,err 包含 code、message粪摘、isRequestError 三個屬性
  }
});

前端代碼:發(fā)送請求使用 axios

<input type="file" id="upload" accept="image/*" />
const fileInput = document.getElementById('upload');
fileInput.addEventListener('change', async function(e) {
  const file = e.target.files[0]; // Blob瀑晒,文件流對象
  // 通過后端接口獲取七牛云的 token
  const res = await axios.get('/qiniuToken');
  const { token, key } = res.data;
  const putExtra = {
    fname: '', // 文件原文件名
    params: {}, // 用來放置自定義變量
    mimeType: null // 用來限制上傳文件類型,為 null 時表示不對文件類型限制徘意;eg: ["image/png", "image/jpeg"]
  };
  const config = {
    useCdnDomain: true, // 開啟 cdn 加速域名
    region: null, // 為 null 會自動解析上傳區(qū)域
  };
  // 調(diào)用 qiniu.upload 上傳圖片苔悦,生成 observable 實例
  const observable = qiniu.upload(file, key, token, putExtra, config);
  // 調(diào)用 observable 的 subscribe 方法,獲取響應結(jié)果
  observable.subscribe({
    complete(data) {
      const { key } = data;
      // 把返回的 key 與 域名拼接椎咧,就是圖片地址
      const url = '配置的域名' + key;
    },
    next(res) {
      // ...
    },
    error(err) {
      // ...
    }
  });
});

API上傳

首先拿到 token玖详,然后調(diào)用上傳的 api ,不同的空間區(qū)域?qū)煌慕涌诘刂芬赝耍业目臻g是華南區(qū)域,接口地址:http://upload-z2.qiniu.com

const fileInput = document.getElementById('upload');
fileInput.addEventListener('change', async function(e) {
  const file = e.target.files[0]; // Blob劳澄,文件流對象
  // 通過后端接口獲取七牛云的 token
  const res = await axios.get('/qiniuToken');
  const { token, key } = res.data;
  const formData = new FormData();
  formData.append('token', token);
  formData.append('key', key); // key:文件名地技,可以不傳,如果不傳七牛則會自動生成隨機文件名 hash
  formData.append('file', file);
  const response = await axios.post('http://upload-z2.qiniu.com', formData);
  const url = '七牛云倉庫配置的域名' + response.key;
});

上面的兩種上傳方式秒拔,后端需要返回 token

后端代碼:后端實現(xiàn)使用 koa

因為只需要返回 token莫矗,所以相對簡單

const qiniu = require('qiniu')

router.get('/qiniuToken', async (ctx) => {
  // accessKey,secretKey 在個人中心可以查看
  const accessKey = 'your access key';
  const secretKey = 'your secret key';
  // 鑒權(quán)對象 mac
  const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
  const options = {
    scope: 'your bucket' // 倉庫名
  };
  const putPolicy = new qiniu.rs.PutPolicy(options);
  const token = putPolicy.uploadToken(mac);
  const key = +new Date() + Math.random().toString(16).slice(2); // key 只需要隨機不重復就可以
  ctx.body = { status: 1, data: { token, key } };
});

后端直傳

前端只需要傳遞一個 file 文件流對象

fileInput.addEventListener('change', async function(e) {
  const file = e.target.files[0]; // Blob砂缩,文件流對象
  const formData = new FormData();
  formData.append('file', formData); // file 是后端接受的字段
  // axios 識別到參數(shù)為 formData 類型后作谚,會自動修改 Content-Type 為 multipart/form-data
  const res = await axios.post('/qiniu', formData);
  const { url } = res.data;
});

后端需要調(diào)用 qiniu-sdk

先下載 koa-body

npm i -S koa-body
const koaBody = require('koa-body');
const koaBodyOpts = {
  multipart: true, // 默認不會接受 formData 參數(shù),需要開啟
  formLimit: '15mb' // 默認 56 kb庵芭,盡量設置大一些
};
// 在全局使用 koa-body
app.use(koaBody(koaBodyOpts));

// 在某個路由使用
router.post('/qiniu', koaBody(koaBodyOpts), async (ctx) => {
  const { file } = ctx.request.body.files;
  const ext = path.extname(file.name);
  const fileName = +new Date() + ext;
  const localFile = file.path;
  try {
    const res = await qiniuPut(fileName, localFile);
    const url = qiniuOpts.url + res.key;
    ctx.body = { status: 1, data: { url } };
  } catch (e) {
    console.log(e);
    ctx.body = { status: 0, msg: '上傳失敗' };
  }
});

// 獲取七牛云 token
const qiniuToken = () => {
  const accessKey = 'your access key';
  const secretKey = 'your secret key';
  const mac = new qiniu.auth.digest.Mac(accessKey, secretKey);
  const options = {
    scope: 'your bucket'
  };
  const putPolicy = new qiniu.rs.PutPolicy(options);
  const uploadToken = putPolicy.uploadToken(mac);
  return uploadToken;
};

// 七牛云文件上傳
const qiniuPut = (key, localFile) => {
  const uploadToken = qiniuToken();
  const config = new qiniu.conf.Config();
  // 空間對應的機房
  config.zone = qiniu.zone.Zone_z2;
  const formUploader = new qiniu.form_up.FormUploader(config);
  const putExtra = new qiniu.form_up.PutExtra();
  return new Promise((resolve, reject) => {
    formUploader.putFile(uploadToken, key, localFile, putExtra, (respErr, respBody, respInfo) => {
      if (respErr) {
        reject(respErr);
      } else {
        resolve(respBody);
      }
    });
  });
}

七牛云的 api 還有很多妹懒,有興趣可以看看文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市双吆,隨后出現(xiàn)的幾起案子眨唬,更是在濱河造成了極大的恐慌会前,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匾竿,死亡現(xiàn)場離奇詭異瓦宜,居然都是意外死亡,警方通過查閱死者的電腦和手機岭妖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門临庇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人昵慌,你說我怎么就攤上這事假夺。” “怎么了废离?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵侄泽,是天一觀的道長。 經(jīng)常有香客問我蜻韭,道長悼尾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任肖方,我火速辦了婚禮闺魏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘俯画。我一直安慰自己析桥,他們只是感情好,可當我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布艰垂。 她就那樣靜靜地躺著泡仗,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猜憎。 梳的紋絲不亂的頭發(fā)上娩怎,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機與錄音胰柑,去河邊找鬼截亦。 笑死,一個胖子當著我的面吹牛柬讨,可吹牛的內(nèi)容都是我干的崩瓤。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼踩官,長吁一口氣:“原來是場噩夢啊……” “哼却桶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔗牡,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤肾扰,失蹤者是張志新(化名)和其女友劉穎畴嘶,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體集晚,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡窗悯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了偷拔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒋院。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖莲绰,靈堂內(nèi)的尸體忽然破棺而出欺旧,到底是詐尸還是另有隱情,我是刑警寧澤蛤签,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布辞友,位于F島的核電站,受9級特大地震影響震肮,放射性物質(zhì)發(fā)生泄漏称龙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一戳晌、第九天 我趴在偏房一處隱蔽的房頂上張望鲫尊。 院中可真熱鬧,春花似錦沦偎、人聲如沸疫向。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搔驼。三九已至,卻和暖如春侈询,著一層夾襖步出監(jiān)牢的瞬間舌涨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工妄荔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留泼菌,地道東北人谍肤。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓啦租,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荒揣。 傳聞我的和親對象是個殘疾皇子篷角,可洞房花燭夜當晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容