对于饭圈人迷来说说事实就是黑 發表於 2020-7-9 23:31:00

uni-app实现文件上传功能

<h3 id="uni-app实现文件上传功能">uni-app实现文件上传功能</h3>
<p>目前找到的比较好用的一款第三方插件<br>
文件上传插件地址 https://ext.dcloud.net.cn/plugin?id=1015<br>
插件下载选择下载示例项目zip,可以直接运行项目查看效果</p>
<p>目录结构如下<br>
<img src="https://img-blog.csdnimg.cn/20200317231930880.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3d1c2VqaWVnZTY=,size_16,color_FFFFFF,t_70"></p>
<h4 id="indexvue是使用文件上传功能的当前页面">index.vue,是使用文件上传功能的当前页面</h4>
<p>@up-success="onSuccess"是文件上传成功以后回传的数据</p>
<pre><code>&lt;template&gt;
        &lt;view&gt;
                &lt;l-file ref="lFile" @up-success="onSuccess"&gt;&lt;/l-file&gt;
                &lt;view class="padding text-center"&gt;
                        &lt;view class="padding"&gt;
                                &lt;button @tap="onUpload"&gt;上传&lt;/button&gt;
                        &lt;/view&gt;
                &lt;/view&gt;
        &lt;/view&gt;
&lt;/template&gt;
&lt;script&gt;
        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'
                                })
                        }
                }
        }
&lt;/script&gt;
</code></pre>
<br>
<h4 id="l-filevue是文件上传功能的封装组件最后加载的是indexhtml文件">l-file.vue,是文件上传功能的封装组件,最后加载的是index.html文件</h4>
<p>wv.overrideUrlLoading监听返回的文件上传结果。</p>
<pre><code>getRequest(url) {
        let theRequest = new Object();
        let index = url.indexOf("?");
        if (index != -1) {
                let str = url.substring(index+1);
                let strs = str.split("&amp;");
                for(let i = 0; i &lt; strs.length; i ++) {
                        theRequest.split("=")]=unescape(strs.split("="));
                }
        }
        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)=&gt;{
                let {fileName,id} = this.getRequest(e.url);
                return this.onCommit(
                this.$emit('up-success',{fileName,data: {id,statusCode: 200}})
                );
        });
        // #endif
}
</code></pre>
<br>
<h4 id="indexhtml-源码">index.html 源码</h4>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="zh-cn"&gt;

        &lt;head&gt;
                &lt;meta charset="UTF-8"&gt;
                &lt;title class="title"&gt;[文件管理器]&lt;/title&gt;
                &lt;meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" /&gt;
                &lt;style type="text/css"&gt;
                        .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;}
                &lt;/style&gt;
        &lt;/head&gt;

        &lt;body&gt;
               
                &lt;div class="content"&gt;
                       
                        &lt;div class="fixed mask"&gt;&lt;/div&gt;
                       
                        &lt;div align="center" class="fixed tis"&gt;
                                &lt;div class="tis-content"&gt;
                                        &lt;div&gt;
                                                &lt;img src="../../static/logo.png" &gt;
                                        &lt;/div&gt;
                                        &lt;div class="tis-progress"&gt;
                                                努力上传中..
                                        &lt;/div&gt;
                                        &lt;div class="cancel"&gt;
                                                &lt;button type="button" class="cancel-btn"&gt;取消上传&lt;/button&gt;
                                        &lt;/div&gt;
                                &lt;/div&gt;
                        &lt;/div&gt;
                       
                        &lt;div class="fixed file-content"&gt;
                                &lt;div class="btn"&gt;
                                        &lt;button type="button" class="btn-bg"&gt;打开文件管理器&lt;/button&gt;
                                        &lt;input class="file" type="file" /&gt;
                                &lt;/div&gt;
                        &lt;/div&gt;
                &lt;/div&gt;
               
                &lt;script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"&gt;&lt;/script&gt;
                &lt;script src="js/h5-uploader.js" type="text/javascript" charset="utf-8"&gt;&lt;/script&gt;
        &lt;/body&gt;

&lt;/html&gt;

</code></pre>
<br>
<h4 id="h5-uploaderjs-源码">h5-uploader.js 源码</h4>
<p>负责h5代码上传文件及其进度展示,及上传结果回传</p>
<pre><code>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 = {}) =&gt; {
        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);
        }
       
        let xhr = new XMLHttpRequest();
        xhr.open("POST", url, true);
       
        for (let keys in header) {
                xhr.setRequestHeader(keys, header);
        }
        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(()=&gt;{
                        tis.style.display = 'none';
                        plus.webview.currentWebview().close();
                },1000);
        };
       
        xhr.onreadystatechange = (ev) =&gt; {
               
                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}&amp;id=${xhr.responseText}`;
                               
                        }
                        else {
                                progress.innerText = '上传失败了';
                        }
                       
                        setTimeout(()=&gt;{
                                tis.style.display = 'none';
                                plus.webview.currentWebview().close();
                        },1000);
                       
                }
        };
        xhr.send(formData);
       
        cancel.addEventListener("click", ()=&gt;{
                xhr.abort();
                plus.webview.currentWebview().close();
        });
}


mask.addEventListener("click", () =&gt; {
        plus.webview.currentWebview().close();
});

document.addEventListener('UniAppJSBridgeReady', () =&gt; {
        let {url,key,header,formData} = plus.webview.currentWebview();
        fileDom.addEventListener('change', (event) =&gt; {
                let file = fileDom.files;
                if(file.size &gt; (1024*1024 * 10)) {
                        plus.nativeUI.toast('单个文件不能超过10M,请重新上传');
                        return;
                }
                console.log(file.name);
                createUpload(file, url, key,header,formData);
        }, false);
});
</code></pre>
<p>插件地址 https://ext.dcloud.net.cn/plugin?id=1015</p><br><br>
来源:https://www.cnblogs.com/that-jay/p/13276926.html
頁: [1]
查看完整版本: uni-app实现文件上传功能