#> RESTKHZ _

休止千鹤 | 我依旧是一名平凡的学生

微信小程序云存储图片上传及UI框架兼容补丁(wx.cloud.uploadFile, Wux)

  休止千鹤  |    04/04/2021

最近在折腾微信小程序, 因为我没有备案域名所以目前只能考虑通过调用微信自己提供的serverless API进行开发.
5G的免费存储,千次操作,带1G的CDN流量,还是很可观的. Serverless概念, 不需要备案, 没有理由不用吧?
但是我也遇到一些问题, 听我慢慢说来: 我开发的项目对于个人来说有点点大, 有使用框架的必要. 一开始用的iView组件库, 后来又自己补了一个客户图片上传功能,但是iView没有upload这个组件. 于是我又在项目里加了Wux UI混合使用.
可是当我看起Wux的文档的时候人傻了: 根本没有云存储上传支持.
赶快又去看了看微信亲儿子 weui, 也没有云存储上传支持.
哦豁.亲妈不管.

本文接下来的代码是Wux的4e19b28 on 29 Nov 2020, 未来下面的代码可能会变化,不确保长期有效,当然Wux提供云上传支持那最好了.

我其实不太会ES6那啥玩意, 但是这个补丁得我还是得打.如果有大佬看见我的方法,别见笑.

好在微信组件库并没有特别复杂的依赖关系, 根据Wux文档:量身定制在github中下载的那个项目中的src/upload/index.js能看到upload的可读源码. 在文件的380行我们可以找到wx.uploadFile函数的调用, 观察是如何运行的:

if (!this.tempFilePaths.length) return

const { url, name, header, formData, disabled, progress } = this.data
const file = this.tempFilePaths.shift()
const { uid, url: filePath } = file

if (!url || !filePath || disabled) return

this.onStart(file)

this.uploadTask[uid] = wx.uploadFile({
                url,
                filePath,
                name,
                header,
                formData,
                success: (res) => this.onSuccess(file, res),
                fail: (res) => this.onFail(file, res),
                complete: (res) => {
                    delete this.uploadTask[uid]
                    this.triggerEvent('complete', res)
                    this.uploadFile()
                },
            })
            // ...

根据微信官方API文档:
wx.uploadFile
wx.cloud.uploadFile

对照一下, 普通上传必须要url, filePath, name三个参数, 云上传要cloudPath,filePath这两个参数.
filePath完全可以重用, url可以用于控制识别应该用那个函数,毕竟url格式应该是固定的. 至于name则是可以合并在后者cloudPath之中的.
另一方面这两个API返回的对象也是一样的.所以应该可以考虑补丁.

简单的说,我就是让url这个参数格式为开头是cloud的时候就使用云函数,除去cloud和分割符后面就是云函数路径,加上name就是cloudPath可以上传了.

比如url是cloud:avatar, 那就是上传到云存储的avatar路径之下

我自己的脏patch代码如下

        uploadFile() {
            if (!this.tempFilePaths.length) return

            const { url, name, header, formData, disabled, progress } = this.data
            const file = this.tempFilePaths.shift()
            const { uid, url: filePath } = file

            if (!url || !filePath || disabled) return

            this.onStart(file)

            //云上传补丁 begin
            //console.log('[*] upload:'+url.substring(6,) + '/' + name)
            if (url.substring(0,5) === "cloud") {        //检查url参数开头是否是cloud
                this.uploadTask[uid] = wx.cloud.uploadFile({
                    cloudPath: url.substring(6,) + '/' + name,        //拼凑cloudPath
                    filePath,        //直接利用filePath
                    success: (res) => this.onSuccess(file, res),
                    fail: (res) => this.onFail(file, res),
                    complete: (res) => {
                        delete this.uploadTask[uid]
                        this.triggerEvent('complete', res)
                        this.uploadFile()
                    },
                })
            } else {
                this.uploadTask[uid] = wx.uploadFile({        //原本的调用
                    url,
                    filePath,
                    name,
                    header,
                    formData,
                    success: (res) => this.onSuccess(file, res),
                    fail: (res) => this.onFail(file, res),
                    complete: (res) => {
                        delete this.uploadTask[uid]
                        this.triggerEvent('complete', res)
                        this.uploadFile()
                    },
                })
            }
            //云上传补丁 end
            // .....

对应wxml, 只用在url那边如此填写:

<wux-upload listType="picture-card" defaultFileList="{{ fileList }}" max="3" url="cloud:avatar"  name="{{imgName}}" bind:change="uploadChange" bind:success="uploadSuccess" bind:fail="uploadFail"  bind:preview="uploadPreview" bind:before="uploadBefore">
        <text>上传</text>
</wux-upload>

这个patch并不是个很好的方案,但是的确兼容了.
希望未来wux能加入这个API的支持.


Views:

 Comments


(no comments...maybe you can be the first?)