Multi image upload (compatible with wechat applet, only single image upload) – problems encountered in developing uniapp project (main H5, wechat applet)

Time:2020-7-11

Demo:uni-app template GitHub Address

problem


In demand, multiple images need to be uploaded, but wechat applet can only upload single image, and multi image upload only supports app and H5.

Multi image upload (compatible with wechat applet, only single image upload) - problems encountered in developing uniapp project (main H5, wechat applet)

If you can only upload pictures one by one, the user experience is quite poor. I believe that the users who upload will be crazy

thinking


The official document also gives a solution, which is to call the API repeatedlyuni.uploadFile

Multi image upload (compatible with wechat applet, only single image upload) - problems encountered in developing uniapp project (main H5, wechat applet)

resolvent


I used the plug-in of the uni app plug-in market (encapsulating the request network request library like Axios, supporting interceptors and task operations), and uni.uploadFile There are also packages.
Multi image upload (compatible with wechat applet, only single image upload) - problems encountered in developing uniapp project (main H5, wechat applet)

Here, I am api.js The method of uploading pictures is also defined in the file of.

//Upload the picture. The interface name is defined according to its own back-end. This interface cannot be called
export const uploadToOss = (params) => axios.upload('/api/upload/xxx', {
    ...params,
    custom: {
        loading: true,
        Loadingtitle: 'uploading...'
    }
})

UploadPic.vue

<template>
    <view class="upload_box">
        <view class="image_list">
            <view class="image_item" v-for="(item, index) in files" :key="index">
                <view class="icon iconfont iconshanchu" @click="removeItem(index)"></view>
                <image :src="item"></image>
            </view>
            <view class="upload" v-if="files.length < limit" @click="handleUpload">
                <view class="icon iconfont iconshangchuan"></view>
                <text>{{ btnText }}</text>
            </view>
        </view>
        <view class="upload_tip" v-if="tip">{{ tip }}</view>
    </view>
</template>

<script>
import { uploadToOss } from '@/api/http';

export default {
    props: {
        //Tips
        tip: {
            type: String,
            default: ''
        },
        //Button text
        btnText: {
            type: String,
            default: ''
        },
        //Limit the number of sheets at most, 1 by default
        limit: {
            type: Number,
            default: 1
        },
        //Image type, used to distinguish multiple image upload components on the same page
        imgType: {
            type: String,
            default: 'image'
        }
    },
    data() {
        return {
            Files: [] // image address collection after uploading pictures
        };
    },
    methods: {
        /**
         *@ description delete picture
         *@ param {number} index index value of the image
         */
        removeItem(index) {
            this.files.splice(index, 1);
            this.sendMessage (); // send message parent component
        },
        /**
         *@ description upload image
         *@ param {string} URL image temporary address
         */
        uploadImg(url) {
            return new Promise((resolve, reject) => {
                uploadToOss({
                    filePath: url,
                    fileType: 'image',
                    name: 'file',
                }).then(res => {
                    if(res._OK) {
                        resolve(res.data.data);
                    } else {
                        uni.showModal({
                            Title: 'prompt',
                            content:  res.data.message  ||'upload failed'
                        })
                        
                        return new Promise.reject(res);
                    }
                }).catch(err => {
                    return new Promise.reject(err);
                })
            })
        },
        
        /**
         *@ description traverses and calls the upload interface
         * @param {Array} tempFilePaths  uni.chooseImage Temporary image address collection returned after picture selection
         *@ returns {array} array the collection of addresses returned on the image server by asynchronously calling the upload interface
         */
        async uploads(tempFilePaths) {
            let arr = [];
            for(let i = 0; i < tempFilePaths.length; i++) {
                arr[i] = await this.uploadImg(tempFilePaths[i]);
            }
            
            return arr;
        },
        
        /**
         *@ description upload image
         */
        handleUpload() {
            let _this = this;
            
            uni.chooseImage({
                count: _this.limit,
                async success(chooseImageRes) {
                    //After selecting the image, call the image upload interface immediately. The await of ES6 must be included by async.
                    let files = await _this.uploads(chooseImageRes.tempFilePaths);

                    _this.files = [..._this.files, ...files];
                    _this.sendMessage (); // send message parent component
                }
            });
        },
        /**
         *@ description sends information to parent component
         */
        sendMessage() {
            this.$emit('on-change', {
                files: this.files,
                imgType: this.imgType
            });
        }
    }
};
</script>

<style lang="scss" scoped>
.upload_box {
    .upload {
        width: 120rpx;
        height: 120rpx;
        border: 2rpx solid #d9d9d9;
        font-size: 24rpx;
        color: #999999;
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: center;
        margin-bottom: 20rpx;

        .iconfont {
            margin-bottom: 8rpx;
        }
    }

    .image_list {
        display: flex;
        flex-wrap: wrap;

        .image_item {
            position: relative;
            width: 120rpx;
            height: 120rpx;
            margin: 0 20rpx 20rpx 0;
            z-index: 1;

            image {
                width: 120rpx;
                height: 120rpx;
            }

            .iconfont {
                color: #ff0000;
                font-size: 30rpx;
                position: absolute;
                z-index: 10;
                right: 0;
                top: 0;
            }
        }
    }
}

.upload_tip {
    color: #999999;
    font-size: 24rpx;
    margin-top: -10rpx;
}
</style>

summary


The interaction and expansibility of the multi graph upload component is not good enough, but it basically meets the needs of the current product. After that, it will continue to be updated iteratively. I hope you can give more comments

Recommended Today

Think about open source project promoting rust search extension: quickly search rust documents in the browser address bar

Open source project name:Rust Search Extension Introduction to open source projects:Quick search for rust documents in the browser address barOpen source project type:teamProject creation time:2020 GitHub data:375 Star,18 ForkGitHub address:https://github.com/huhu/rust-search-extension Rust search extension is a plug-in that can quickly search rust documents, Crites, built-in properties and error codes in the browser address bar. It supports […]