1. 程式人生 > >七牛雲物件儲存客戶端直傳前後端實現 【spring cloud + vue】

七牛雲物件儲存客戶端直傳前後端實現 【spring cloud + vue】

兩種檔案上傳的方式

服務端傳輸

服務端傳輸

客戶端直傳

客戶端直傳

兩種傳輸方式比較

  • 服務端傳輸,所有客戶端的上傳請求需傳送至業務伺服器,再由業務伺服器轉發至檔案伺服器,上傳結果的返回同樣需要業務伺服器的轉發,這樣的操作保證了傳輸的安全,但卻大大提升了業務伺服器的壓力,增加了傳輸的時間及成本;

  • 客戶直傳是由客戶端到業務伺服器取得檔案上傳令牌,然後攜令牌上傳檔案至檔案伺服器,這樣很好的保證了安全的同時,極大的提高了傳輸效率;

客戶端直傳實現

服務端實現

  • 引入七牛的Java SDK
        <dependency>
            <groupId
>
com.qiniu</groupId> <artifactId>qiniu-java-sdk</artifactId> <version>7.2.10</version> </dependency>
  • 提供客戶端獲取upToken介面
@RestController
public class FileUploadApi {

    @Value("${qiniu.ak}")
    private String QINIU_AK;
    @Value
("${qiniu.sk}") private String QINIU_SK; @Value("${qiniu.bucket}") private String QINIU_BUCKET; //獲取七牛雲上傳token @GetMapping(path = "upToken") public String getUpToken() { Auth auth = Auth.create(QINIU_AK, QINIU_SK); String upToken = auth.uploadToken(QINIU_BUCKET); return
upToken; } }

其中BUCKET、AK、SK 在七牛雲控制檯獲取

前端實現

<template>
    <div class="app-container">
        <form id="fileUploadForm" method="post" action="http://up-z2.qiniu.com">
            <input name="file" type="file" />
            <input name="accept" type="hidden" />
        </form>

        <img :src="img" alt="">

        <button @click="upload">上傳</button>
    </div>
</template>

<script>
const qiniu = require('qiniu')
const uuid = require('uuid/v4')
const request = require('../utils/request')
import fileUploadApi from '../api/FileUploadApi'

export default {
    name:'UploadFile',
    data:function(){
        return {
            key:uuid(),
            upToken:'',
            img:'',
        }
    },
    methods:{
        upload:function(){
            const _this = this;
            //上傳的檔名使用uuid
            _this.key = uuid()
            console.log(_this.key)
            //獲取formData
            var formData = new FormData(document.getElementById('fileUploadForm'))
            //從服務端獲取upToken
            fileUploadApi.getUpToken()
                .then(function(data){
                    if(data == null || data.lenth == 0){
                        return
                    }
                    _this.upToken = data.toString()

                    //fileForm,upToken,key,otherOpt
                    //上傳圖片檔案
                    fileUploadApi.upload(formData,_this.upToken,_this.key,null)
                        .then(function(data){
                            if (data.key){
                                //獲取七牛雲key 並生成圖片外鏈 展示
                                _this.img = fileUploadApi.getDownloadURL(data.key)
                            }
                        })
                }).catch(function(){
                    return
                })
        }
    }

}
</script>

這裡主要採用了HTML5 的formData對錶單中的file input進行資料提取,提取出的資料通過axios非同步提交

import request from '../utils/request'
import global from '../utils/global'
/**
 * 檔案上傳API
 */
export default{

    //獲取上傳upToken
    getUpToken:function(){
        return request({
            url:'/hnister-file-service/upToken',
            method:'get'
        })
    },
    //以表單方式上傳檔案 參考:
    //https://developer.qiniu.com/kodo/manual/1272/form-upload
    upload: function(fileForm,upToken,key,otherOpt){
        if (!otherOpt){
            otherOpt = {}
        }

        fileForm.append('key',key)
        fileForm.append('token',upToken)
        for(k in Object.keys(otherOpt)){
            fileForm.append(k,otherOpt[k])
        }
        return request({
            url:global.address.qiniuUploadURL,
            baseURL:'',
            method:'post',
            data:fileForm,
            headers:{'Content-Type':'multipart/form-data'}
        })
    },
    //上傳後返回的key 獲取檔案外鏈
    getDownloadURL:function(key){
        return global.address.qiniuDownloadURL + '/' + key;
    }
}

檔案上傳API

import axios from 'axios'
import global from './global'

// 建立axios例項
const service = axios.create({
    // baseURL: process.env.BASE_API, // api的base_url
    baseURL: global.address.zuul,
    timeout: 15000 // 請求超時時間
})

const responseFun = function (response) {
    return response.data;
}

// respone攔截器
service.interceptors.response.use(
    responseFun,
    error => {
        return Promise.reject(error)
    }
)

export default service;

對axios 進行封裝和攔截

const address = {
    zuul:'http://localhost:10000',
    //七牛雲的華南區檔案上傳地址
    qiniuUploadURL:'http://up-z2.qiniu.com',
    //我的七牛雲圖片下載host
    qiniuDownloadURL:'http://p4fkxpg80.bkt.clouddn.com',
}

export default{
    address
}

儲存全域性變數

前端實現DEMO 的地址:

END

效果