vue+element-ui +koa2 文件上傳騰訊雲踩坑記隨筆

首先,文件上傳那些事兒,從頭補一下https://cloud.tencent.com/developer/article/1004961前端

  • 第一個坑,koa-body的ctx.request獲取

  一開始沒有明確需求,覺得須要先把文件寫到後端,而後再上傳騰訊雲。因此研究了下koa-body怎麼用文件流讀寫文件到後端。web

  而後在獲取ctx.request.body.files.file時怎麼都獲取不到element-ui

  感謝https://www.jianshu.com/p/34d0e1a5ac70後端

  嚴正提醒:api

  新版本的koa-body經過ctx.request.files獲取上傳的文件  
  舊版本的koa-body經過ctx.request.body.files獲取上傳的文件koa

  • 第二個坑,表單上傳前的圖片寬高獲取

  因爲須要在後端請求一個須要當前圖片寬高的接口,而formData中的file並雖然有name、size信息,可是並無圖片的寬高信息async

  因而在前端獲取寬高,並傳送給後端。post

    • tip1:表單提交前寬高獲取

    這裏我用的element-ui,前端代碼以下ui

<template>
    <el-upload
            class="upload-demo"
            action="/api/uploadFile"
            :on-preview="handlePreview"
            :on-remove="handleRemove"
            :before-upload="getWidth"
            :file-list="fileList"
            list-type="picture"
            :data="pictureUpload"
    >
        <el-button size="small" type="primary">點擊上傳</el-button>
        <div slot="tip" class="el-upload__tip">只能上傳jpg/png文件,且不超過500kb</div>
    </el-upload>
</template>

    使用fileReader()獲取上傳圖片的寬高 https://www.haorooms.com/post/js_webapi_filereaderthis

<script>
    export default {
        name: "upload",
        data(){
            return {
                pictureUpload: {
                    width: 0,
                    height: 0
                }
            }
        },
        methods: {
            handleRemove(file, fileList) {
                console.log(file, fileList);
            },
            handlePreview(file) {
                console.log(file);
            },
            getWidth(file) {
                // 獲取文件尺寸
                let _this = this;
                return new Promise(function(resolve, reject) {

                    let reader = new FileReader()
                    reader.readAsDataURL(file)
                    reader.onload = function(theFile) {
                        let image = new Image()
                        image.src = theFile.target.result
                        image.onload = function() {
                            console.log(`${this.width}*${this.height}`)
                            console.log(this.width,this.height)
                            console.log(_this.fileList)
                            _this.pictureUpload.width = this.width;
                            _this.pictureUpload.height = this.height;
                            resolve(file);
                        }
                    }
                })
            }
        }

    }
</script>
    • tip2: 在後端如何接收Form Data裏面的寬高呢?其實用ctx.request.body就能夠取到了,和files不一樣

       

 後端的代碼以下

var info = require('../config/info')
var Uploader = require('../modules/cos-uploader')
var JsonProxy = require('../modules/cos-uploader')
var fs = require("fs")
var path = require("path")
const crypto = require('crypto');

let jprxClient = new JsonProxy({env: 'beta'});
async function uploadFile (ctx, next) {
    let file = ctx.request.files.file;// 獲取上傳文件
    let userInfo = {
        "account": "122333221",
        "loginkey": "aaaaaaaaaaaaaaaaaa",
    }
    // 請求cosPath的參數
    let hash = crypto.createHash('sha1');
    let buffer = fs.readFileSync(file.path);
    hash.update(buffer);
    let sha1 = hash.digest('hex');
    let opts = {
        "authCtx": userInfo,
        "photoInfo": {
            "name": file.name,
            "size": file.size,
            "sha": sha1,
            "width": ctx.request.body.width,
            "height": ctx.request.body.height
        }
    };
    console.log('opts__________________',opts)
    let cosPath = '';
   // 接口請求省略
        // 上傳騰訊雲
        let localPath = file.path;
        let groupId = "temp";
        let remotePath = _getRemotePath(localPath, groupId);

        let uploader = new Uploader({
            // AppId: info.cos.AppId,
            SecretId: info.cos.SecretId,
            SecretKey: info.cos.SecretKey
        });
        let uploadOptions = {
            bucket: info.cos.Bucket+ '-' + info.cos.AppId,
            region: info.cos.Region,
            remotePath: remotePath,
            localPath: localPath
        };
        console.log('uploadOptions', uploadOptions);
        let uploadResult = await uploader.up(uploadOptions);
        console.log('upLoadResult____________________',uploadResult);
        if(uploadResult.statusCode == 200) {
            let opts = {
                "authCtx": userInfo,
                "sha": sha1
            };
            console.log('callBackOpts____________________________',opts)
            // 請求接口省略
            ctx.body = {
                location: uploadResult.Location,
                status: 0,
                message: 'success'
            }
        }else {
            ctx.body = {
                status: -1,
                message: uploadResult
            }
        }
}
// 可獲取cosPath後不須要
function _getRemotePath(filePath, groupId) {
    var groupId = groupId || 'common_group_id';
    var hash = crypto.createHmac('sha256', 'useforalbums').update(fs.readFileSync(filePath)).digest('hex');
    return `albumgroup_${global._ENV === 'production' ? 'production' : 'beta'}/${groupId}/${hash}`;
}
module.exports = {
    uploadFile,
};
相關文章
相關標籤/搜索