博客 / 詳情

返回

uniapp實現文件選擇上傳,支持App/小程序/H5

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顆小星星以作鼓勵哈~
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.