上傳圖片是很常見的需求,方法也有不少。本次使用的是七牛雲的對象存儲,七牛雲的oss作的仍是比較出色的。html
七牛雲的上傳大致分爲兩種前端
受權式上傳其實還分兩種,一種是調用 qiniu SDK,一種直接調用七牛的上傳接口node
本文會把兩種方法都實現,實際開發根據狀況選用ios
formData + axios + koa + koa-bodyshell
這種上傳方式,後端只須要返回七牛的 token,由前端調用 SDK 或者 上傳接口npm
七牛雲的sdk能夠經過script標籤引入axios
https://unpkg.com/qiniu-js@2.4.0/dist/qiniu.min.js
qiniu
的對象經過npm安裝後端
npm install qiniu-js --save
import * as qiniu from 'qiniu-js'
qiniu-sdkapi
主要api,qiniu.upload(file, key, token, putExtra, config)app
調用成功後返回一個observable對象,調用它的 subscribe 方法獲取到響應結果
observable.subscribe({ complete(res) { // 上傳完成的響應信息,res 包含 hash、key兩個屬性(默認) }, next(res) { // 接收上傳進度信息,res 包含loaded、total、percent三個屬性,提供上傳進度信息。 }, error(err) { // 上傳錯誤觸發,err 包含 code、message、isRequestError 三個屬性 } });
前端代碼:發送請求使用 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 會自動解析上傳區域 }; // 調用 qiniu.upload 上傳圖片,生成 observable 實例 const observable = qiniu.upload(file, key, token, putExtra, config); // 調用 observable 的 subscribe 方法,獲取響應結果 observable.subscribe({ complete(data) { const { key } = data; // 把返回的 key 與 域名拼接,就是圖片地址 const url = '配置的域名' + key; }, next(res) { // ... }, error(err) { // ... } }); });
首先拿到 token,而後調用上傳的 api ,不一樣的空間區域對應不一樣的接口地址,個人空間是華南區域,接口地址: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
後端代碼:後端實現使用 koa
由於只須要返回 token,因此相對簡單
const qiniu = require('qiniu') router.get('/qiniuToken', async (ctx) => { // accessKey,secretKey 在我的中心能夠查看 const accessKey = 'your access key'; const secretKey = 'your secret key'; // 鑑權對象 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 識別到參數爲 formData 類型後,會自動修改 Content-Type 爲 multipart/form-data const res = await axios.post('/qiniu', formData); const { url } = res.data; });
後端須要調用 qiniu-sdk
先下載 koa-body
npm i -S koa-body
const koaBody = require('koa-body'); const koaBodyOpts = { multipart: true, // 默認不會接受 formData 參數,須要開啓 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 還有不少,有興趣能夠看看文檔