美文网首页
uni-app实现文件上传功能

uni-app实现文件上传功能

作者: 圣剑Jay | 来源:发表于2020-04-28 12:49 被阅读0次

    uni-app实现文件上传功能

    目前找到的比较好用的一款第三方插件
    文件上传插件地址 https://ext.dcloud.net.cn/plugin?id=1015
    插件下载选择下载示例项目zip ,可以直接运行项目查看效果

    目录结构如下


    20200317231930880.png

    index.vue,是使用文件上传功能的当前页面

    @up-success="onSuccess" 是文件上传成功以后回传的数据

    <template>
        <view>
            <l-file ref="lFile" @up-success="onSuccess"></l-file>
            <view class="padding text-center">
                <view class="padding">
                    <button @tap="onUpload">上传</button>
                </view>
            </view>
        </view>
    </template>
    <script>
        import lFile from '@/components/l-file/l-file.vue'
        export default {
            components:{lFile},
            data() {
                return {
                }
            },
            methods: {
                /* 上传 */
                onUpload() { 
                    this.$refs.lFile.upload({
                        // #ifdef APP-PLUS
                        currentWebview: this.$mp.page.$getAppWebview(),
                        // #endif
                        //非真实地址,记得更换
                         url: 'https://www.example.com/upload',
                        //默认file,上传文件的key
                        name: 'uploadFile',
                        // header: {'Content-Type':'类型','Authorization':'token'},
                        //...其他参数
                    });
                },
                onSuccess(res) {
                    console.log('上传成功回调=====33====',JSON.stringify(res));
                    uni.showToast({
                        title: JSON.stringify(res),
                        icon: 'none'
                    })
                }
            }
        }
    </script>
    

    l-file.vue,是文件上传功能的封装组件,最后加载的是index.html文件

    wv.overrideUrlLoading 监听返回的文件上传结果。

    getRequest(url) {  
        let theRequest = new Object(); 
        let index = url.indexOf("?");
        if (index != -1) {  
            let str = url.substring(index+1);  
            let strs = str.split("&");  
            for(let i = 0; i < strs.length; i ++) {  
                theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);  
            } 
        }  
        return theRequest;  
    },
    appChooseFile({currentWebview,url,name = 'file',header,...formData} = {}) {
        // #ifdef APP-PLUS
        let wv = plus.webview.create("","/hybrid/html/index.html",{
            'uni-app': 'none', //不加载uni-app渲染层框架,避免样式冲突
            top: 0,
            height: '100%',
            background: 'transparent'
        },{
            url,
            header,
            key: name,
            ...formData,
        });
        wv.loadURL("/hybrid/html/index.html")
        currentWebview.append(wv);
        wv.overrideUrlLoading({mode:'reject'},(e)=>{
            let {fileName,id} = this.getRequest(e.url);
            return this.onCommit(
            this.$emit('up-success',{fileName,data: {id,statusCode: 200}})
            );
        });
        // #endif
    }
    

    index.html 源码

    <!DOCTYPE html>
    <html lang="zh-cn">
    
        <head>
            <meta charset="UTF-8">
            <title class="title">[文件管理器]</title>
            <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
            <style type="text/css">
                .content {background: transparent;}
                .fixed {position: fixed;bottom: 0;left: 0;right: 0;width: 100%;}
                .content .mask {top: 0;background: rgba(0,0,0,.4);z-index: 90;}
                .content .file-content {z-index: 91;height: 60px;background: #fff;text-align: center;}
                .btn {position: relative;}
                .btn .file {position: absolute;z-index: 93;left: 0;right: 0;top: 0;bottom: 0;height: 60px;width: 100%;opacity: 0;}
                .btn-bg {margin-top: 10px;background: #0066CC;color: #fff;width: 80%;height: 40px;border: 0;border-radius: 5px;}
                .tis {top: 0;z-index: 95;display: none;justify-content: center;align-items: center;}
                .tis .tis-content {background: #fff;width: 60%;border-radius: 10px;padding: 20px 0;}
                .tis .tis-content img {width: 50px;height: 50px;}
                .tis-progress {margin: 10px 0;color: #999;}
                .cancel-btn {margin-top: 30px;height: 30px;line-height: 1;padding: 0 2em;background: #e3e3e3;color: #898989;border: 0;border-radius: 5px;}
            </style>
        </head>
    
        <body>
            
            <div class="content">
                
                <div class="fixed mask"></div>
                
                <div align="center" class="fixed tis">
                    <div class="tis-content">
                        <div>
                            <img src="../../static/logo.png" >
                        </div>
                        <div class="tis-progress">
                            努力上传中..
                        </div>
                        <div class="cancel">
                            <button type="button" class="cancel-btn">取消上传</button>
                        </div>
                    </div>
                </div>
                
                <div class="fixed file-content">
                    <div class="btn">
                        <button type="button" class="btn-bg">打开文件管理器</button>
                        <input class="file" type="file" />
                    </div>
                </div>
            </div>
            
            <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
            <script src="js/h5-uploader.js" type="text/javascript" charset="utf-8"></script>
        </body>
    
    </html>
    
    

    h5-uploader.js 源码

    负责h5代码上传文件及其进度展示,及上传结果回传

    let mask = document.querySelector(".mask");
    let fileDom = document.querySelector(".file");
    let tis = document.querySelector(".tis");
    let progress = document.querySelector(".tis-progress");
    let cancel = document.querySelector(".cancel-btn");
    
    
    let createUpload = (file, url, key='file', header = {},data = {}) => {
        console.log(`
        上传地址:${url}\n
        请求头:${JSON.stringify(header)}\n
        参数:${JSON.stringify(data)}
        `);
        if (!url) {return;}
        tis.style.display = 'flex';
        
        let formData = new FormData();
            formData.append(key, file);
        
        for (let keys in data) {
            formData.append(keys, data[keys]);
        }
        
        let xhr = new XMLHttpRequest();
        xhr.open("POST", url, true);
        
        for (let keys in header) {
            xhr.setRequestHeader(keys, header[keys]);
        }
        xhr.upload.addEventListener("progress", function(event) {
            if(event.lengthComputable){
                let percent = Math.ceil(event.loaded * 100 / event.total) + "%";
                progress.innerText = `努力上传中..${percent}`;
            }
        }, false);
        
        xhr.ontimeout = function(){
            // xhr请求超时事件处理
            progress.innerText = '请求超时';
            setTimeout(()=>{
                tis.style.display = 'none';
                plus.webview.currentWebview().close();
            },1000);
        };
        
        xhr.onreadystatechange = (ev) => {
            
            if(xhr.readyState == 4) {
                console.log('status:'+xhr.status);
                
                if (xhr.status == 200) {
                    progress.innerText = '上传成功';
                    console.log('返回数据:'+xhr.responseText);
                    location.href = `callback?fileName=${file.name}&id=${xhr.responseText}`;
                    
                }
                else {
                    progress.innerText = '上传失败了';
                }
                
                setTimeout(()=>{
                    tis.style.display = 'none';
                    plus.webview.currentWebview().close();
                },1000);
                
            }
        };
        xhr.send(formData);
        
        cancel.addEventListener("click", ()=>{
            xhr.abort();
            plus.webview.currentWebview().close();
        });
    }
    
    
    mask.addEventListener("click", () => {
        plus.webview.currentWebview().close();
    });
    
    document.addEventListener('UniAppJSBridgeReady', () => {
        let {url,key,header,formData} = plus.webview.currentWebview();
        fileDom.addEventListener('change', (event) => {
            let file = fileDom.files[0];
            if(file.size > (1024*1024 * 10)) {
                plus.nativeUI.toast('单个文件不能超过10M,请重新上传');
                return;
            }
            console.log(file.name);
            createUpload(file, url, key,header,formData);
        }, false);
    });
    

    插件地址 https://ext.dcloud.net.cn/plugin?id=1015

    相关文章

      网友评论

          本文标题:uni-app实现文件上传功能

          本文链接:https://www.haomeiwen.com/subject/uvjvwhtx.html