关于uniapp:uniapp实现文件选择上传支持App小程序H5

61次阅读

共计 7420 个字符,预计需要花费 19 分钟才能阅读完成。

lsj-upload

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

不分明应用形式可点击右侧导入示例我的项目运行残缺示例

此次更新 2.0 与 1.0 应用形式略有差别,已应用 1.0 的同学自行斟酌是否更新到 2.0 版本!!!

应用插件有任何问题欢送退出 QQ 探讨群:

  • 群 1:701468256(已满)
  • 群 2:469580165(已满)
  • 群 3:667530868

若能帮到你请高抬贵手点亮 5 颗星~

重要提醒

组件是窗口级滚动,不要在 scroll-view 内应用!!

组件是窗口级滚动,不要在 scroll-view 内应用!!

组件是窗口级滚动,不要在 scroll-view 内应用!!

控件的 height 高度应与 slot 自定义内容高度保持一致

nvue 窗口只能应用固定模式 position=absolute

show() 当 DOM 重排后在 this.$nextTick 内调用 show(),控件定位会更加精确

hide() APP 端 webview 层级比 view 高,如不心愿触发点击时,应调用 hide 暗藏控件,反之调用 show

若 iOS 端跨域服务端同学切实配置不好,可把 hybrid 下 html 目录放到服务器去,同源则不存在跨域问题。

小程序端因 hybrid 不能应用本地 HTML,所以插件提供的是从微信音讯列表拉取文件并抉择,请知悉。

file 对象不是 object 对象,也不能转 json 字符串,如果你打印 file 那就是 {},能够打印 file.name 和 file.size。

返回的 path 是个 blob 类型,仅供用于文件回显,插件已内置好上传函数,调用上传会主动提交待上传文件,若非要本人拿 path 去搞上传那你本人解决。


应用阐明

属性 是否必填 值类型 默认值 阐明
width String 100% 容器宽度
height String 80rpx 容器高度
debug Boolean false 打印调试日志
option Object 文件上传接口相干参数
instantly Boolean false true= 主动上传
count Number 10 附件抉择下限 (个)
size Number 10 附件大小下限 (M)
wxFileType String all 微信小程序文件选择器格局限度 (all= 从所有文件抉择,video= 只能抉择视频文件,image= 只能抉择图片文件,file= 能够抉择除了图片和视频之外的其它的文件)
accept String 文件选择器 input file 格局限度 (局部机型不兼容,倡议应用 formats)
formats String 限度容许上传的格局,空串 = 不限度,默认为空,多个格局以逗号隔开,例如 png,jpg,pdf
childId String lsjUpload 控件的 id(仅 APP 无效,利用内每个控件命名一个惟一 Id,不同窗口也不要同名 Id)
position String static 控件的定位模式 (static= 控件随页面滚动;absolute= 控件在页面中相对定位,不随窗口内容滚动)
top,left,right,bottom [Number,String] 0 设置控件相对地位,position=absolute 时无效
@change Function Map 抉择文件触发,返回所有已抉择文件 Map 汇合
@progress Function Object 上传过程中产生状态变动的文件对象,需通过 set 更新至 Map 汇合
@uploadEnd Function Object 上传完结回调,返回参数与 progress 统一

option 阐明

参数 是否必填 阐明
url 上传接口地址
name 上传接口文件 key,默认为 file
header 上传接口申请头
formData 上传接口额定参数

ref 调用

作用 办法名 传入参数 阐明
显示控件 show 控件显示状态下可触发点击
暗藏控件 hide 控件暗藏状态下不触发点击
动静设置文件列表 setFiles [Array,Map] files 传入格局请与组件抉择返回格局保持一致,且 name 为必须属性,可查看下方演示
动静更新参数 setData [String] name,[any] value name 反对 a.b 和 a[b],可查看下方演示
移除抉择的文件 clear [String] name 不传参数清空所有文件,传入文件 name 时删除该 name 的文件
手动上传 upload [String] name 不传参数默认顺次上传所有 type=waiting 的文件,传入文件 name 时不关怀 type 是否为 waiting,独自上传指定 name 的文件

progress 返回对象字段阐明

字段 阐明
file 文件对象
name 文件名称
size 文件大小
type 文件上传状态:waiting(期待上传)、loading(上传中)、success(胜利)、fail(失败)
responseText 上传胜利后服务端返回数据 (仅 type 为 success 时存在)

以下演示为 vue 窗口应用形式,nvue 应用区别是必须传入控件相对地位如 top,bottom,left,right,且 position 只能为 absolute,如不分明可点击右侧导入示例我的项目有具体演示代码。

vue:

<lsj-upload 
    ref="lsjUpload"
    childId="upload1"
    :width="width"
    :height="height"
    :option="option"
    :size="size"
    :formats="formats"
    :debug="debug"
    :instantly="instantly"
    @uploadEnd="onuploadEnd"
    @progress="onprogress"
    @change="onChange">
        <view class="btn" :style="{width: width,height: height}"> 抉择附件 </view>
</lsj-upload>


<view class="padding">
            
    <view> 已抉择文件列表:</view>
    
    <!-- #ifndef MP-WEIXIN -->
    <view v-for="(item,index) in files.values()" :key="index">
        <image style="width: 100rpx;height: 100rpx;" :src="item.path" mode="widthFix"></image>
        <text> 提醒:【path 次要用于图片视频类文件回显,他用自行处理】:{{item.path}}</text>
        <text>{{item.name}}</text>
        <text style="margin-left: 10rpx;"> 大小:{{item.size}}</text>
        <text style="margin-left: 10rpx;"> 状态:{{item.type}}</text>
        <text style="margin-left: 10rpx;"> 进度:{{item.progress}}</text>
        <text style="margin-left: 10rpx;" v-if="item.responseText"> 服务端返回演示:{{item.responseText}}</text>
        <text @click="resetUpload(item.name)" v-if="item.type=='fail'"style="margin-left: 10rpx;padding: 0 10rpx;border: 1rpx solid #007AFF;"> 从新上传 </text>
        <text @click="clear(item.name)" style="margin-left: 10rpx;padding: 0 10rpx;border: 1rpx solid #007AFF;"> 删除 </text>
    </view>
    <!-- #endif -->
    
    <!-- #ifdef MP-WEIXIN -->
    <view v-for="(item,index) in wxFiles" :key="index">
        <text>{{item.name}}</text>
        <text style="margin-left: 10rpx;"> 大小:{{item.size}}</text>
        <text style="margin-left: 10rpx;"> 状态:{{item.type}}</text>
        <text style="margin-left: 10rpx;"> 进度:{{item.progress}}</text>
        <view>
            <button @click="resetUpload(item.name)"> 从新上传 </button>
            <button @click="clear(item.name)"> 删除 </button>
        </view>
    </view>
    <!-- #endif -->
    
</view>


  • 函数阐明
export default {data() {
        return {
            // 上传接口参数
            option: {
                // 上传服务器地址,须要替换为你的接口地址
                url: 'http://hl.j56.com/dropbox/document/upload', // 该地址非实在门路,需替换为你我的项目本人的接口地址
                // 上传附件的 key
                name: 'file',
                // 依据你接口需要自定义申请头, 默认不要写 content-type, 让浏览器自适配
                header: {
                    // 示例参数可删除
                    'Authorization': 'bearer eyJhbGciOiJSUzI1NiIsI',
                    'uid': '99',
                    'client': 'app',
                    'accountid': 'DP',
                },
                // 依据你接口需要自定义 body 参数
                formData: {// 'orderId': 1000}
            },
            // 抉择文件后是否立刻主动上传,true= 抉择后立刻上传
            instantly: true,
            // 必传宽高且宽高应与 slot 宽高保持一致
            width: '180rpx',
            height: '180rpx',
            // 限度容许上传的格局,空串 = 不限度,默认为空
            formats: '',
            // 文件上传大小限度
            size: 30,
            // 文件数量限度
            count: 2,
            // 文件回显列表
            files: new Map(),
            // 微信小程序 Map 对象 for 循环不显示,所以转成一般数组,不要问为什么,我也不晓得
            wxFiles: [],
            // 是否打印日志
            debug: true,
            
            
            // 演示用
            tabIndex: 0,
            list:[],}
    },
    onReady() {setTimeout(()=>{console.log('---- 演示动静更新参数 -----');
            this.$refs['lsjUpload'+this.tabIndex].setData('formData.orderId','动静设置的参数'); 
            
            console.log('以下正文内容为 - 动静更新参数更多演示,放开后可查看演示成果');
            // 批改 option 对象的 name 属性
            // this.$refs.lsjUpload.setData('name','myFile');
            
            // 批改 option 对象的 formData 内的属性
            // this.$refs.lsjUpload.setData('formData.appid','1111');
            
            // 替换 option 对象的 formData
            // this.$refs.lsjUpload.setData('formData',{appid:'222'});
            
            // option 对象的 formData 新增属性
            // this.$refs.lsjUpload.setData('formData.newkey','新插入到 formData 的属性');
            
            
            // --------- 演示初始化值,用于已提交后再次编辑时需带入已上传文件 -------
            // 形式 1 = 传入数组
            // let files1 = [{name: '1.png'},{name: '2.png',}];
            
            // 形式 2 = 传入 Map 对象
            // let files2 = new Map();
            // files2.set('1.png',{name: '1.png'})
            
            // 此处调用 setFiles 设置初始 files
            // this.$refs.lsjUpload.setFiles(files1);
            
            // 初始化 tab
            this.onTab(0);
        },2000)
    },
    methods: {// 某文件上传完结回调 ( 成功失败都回调)
        onuploadEnd(item) {console.log(`${item.name} 已上传完结,上传状态 =${item.type}`);
            
            // 更新以后窗口状态变动的文件
            this.files.set(item.name,item);
            
            // --- 可删除 -- 演示上传实现后取服务端数据
            if (item['responseText']) {console.log('演示服务器返回的字符串 JSON 转 Object 对象');
                this.files.get(item.name).responseText = JSON.parse(item.responseText);
            }
            
            // 微信小程序 Map 对象 for 循环不显示,所以转成一般数组,// 如果你用不惯 Map 对象,也能够像这样转一般数组,组件应用 Map 次要是防止重复文件去重操作
            // #ifdef MP-WEIXIN
            this.wxFiles = [...this.files.values()];
            // #endif
            
            // 强制更新视图
            this.$forceUpdate();
            
            
            // --- 可删除 -- 演示判断是否所有文件均已上传胜利
            let isAll = [...this.files.values()].find(item=>item.type!=='success');
            if (!isAll) {console.log('已全副上传完毕');
            }
            else {console.log(isAll.name+'待上传');
            }
            
        },
        // 上传进度回调
        onprogress(item) {
            // 更新以后状态变动的文件
            this.files.set(item.name,item);
            
            console.log('打印对象',JSON.stringify(this.files.get(item.name)));
            // 微信小程序 Map 对象 for 循环不显示,所以转成一般数组,不要问为什么,我也不晓得
            // #ifdef MP-WEIXIN
            this.wxFiles = [...this.files.values()];
            // #endif
            
            // 强制更新视图
            this.$forceUpdate();},
        // 文件抉择回调
        onChange(files) {console.log('以后抉择的文件列表:',JSON.stringify([...files.values()]));
            // 更新抉择的文件 
            this.files = files;
            // 强制更新视图
            this.$forceUpdate();
            
            // 微信小程序 Map 对象 for 循环不显示,所以转成一般数组,不要问为什么,我也不晓得
            // #ifdef MP-WEIXIN
            this.wxFiles = [...this.files.values()];
            // #endif
            
            // --- 可删除 -- 演示从新定位覆盖层控件
            this.$nextTick(()=>{console.log('演示从新定位');
                this.$refs.lsjUpload0.show();
                this.$refs.lsjUpload1.show();
                this.$refs.lsjUpload2.show();});
            
        },
        // 手动上传
        upload() {
            // name= 指定文件名,不指定则上传所有 type 等于 waiting 和 fail 的文件
            this.$refs['lsjUpload'+this.tabIndex].upload();},
        // 指定上传某个文件
        resetUpload(name) {this.$refs['lsjUpload'+this.tabIndex].upload(name);
        },
        // 移除某个文件
        clear(name) {
            // name= 指定文件名,不传 name 默认移除所有文件
            this.$refs['lsjUpload'+this.tabIndex].clear(name);
        },
        /**
         * --- 可删除 -- 演示在组件上方增加新内容 DOM 变动
         * DOM 重排演示,重排后组件外部 updated 默认会触发 show 办法, 若非凡状况未能触发 updated 也能够手动调用一次 show()
         * 什么是 DOM 重排?自行百度去
         */
        add() {this.list.push('DOM 重排测试');
        },
        /**
         * --- 可删除 -- 演示 Tab 切换时覆盖层是否能被点击
         * APP 端因为是 webview,层级比 view 高,此时若不心愿点击触发抉择文件,须要手动调用 hide()
         * 手动调用 hide 后,须要调用 show() 能力复原覆盖层的点击
         */
        onTab(tabIndex) {this.$refs.lsjUpload0.hide();
            this.$refs.lsjUpload1.hide();
            
            this.tabIndex = tabIndex;
            
            this.$nextTick(()=>{this.$refs['lsjUpload'+this.tabIndex].show();})
            
        },
        /**
         * 关上 nvue 窗口查看非追随窗口滚动成果
         */
        open() {
            uni.navigateTo({url: '/pages/nvue-demo/nvue-demo'});
        }
    }
}

舒适提醒

  • 文件上传
  • 如阐明表白还不够分明,不分明怎么应用可导入残缺示例我的项目运行体验和查看
  • APP 端请优先联调 Android, 上传胜利后再运行 iOS 端,如 iOS 返回 status= 0 则须要后端开启容许跨域;
  • header 的 Content-Type 类型须要与服务端要求统一,否则收不到附件(服务端若没有明文规定则可不写,应用默认匹配)
  • 服务端不分明怎么配置跨域可加群征询,具体百度~
  • 欢送退出 QQ 探讨群:701468256(已满)
  • 欢送退出 QQ 探讨群:469580165(已满)
  • 欢送退出 QQ 探讨群:667530868
  • 若能帮到你还请点亮 5 颗小星星以作激励哈~
  • 若能帮到你还请点亮 5 颗小星星以作激励哈~
  • 若能帮到你还请点亮 5 颗小星星以作激励哈~

正文完
 0