# uni.uploadFile(options)

将本地资源上传到开发者服务器。

# uploadFile 兼容性 ?

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.91 4.11 4.61

推荐上传到uniCloud,uniCloud提供了更便宜CDN和更好的易用性,详见

# 参数

名称 类型 必填
options UploadFileOptions
名称 类型 必备 默认值 兼容性 描述
url string
开发者服务器 url
filePath string null
要上传文件资源的路径, 支持uni.env
name string null
文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容
files Array<UploadFileOptionFiles> null
需要上传的文件列表。
名称 类型 必备 默认值 兼容性 描述
name string "file"
multipart 提交时,表单的项目名,默认为 file,如果 name 不填或填的值相同,可能导致服务端读取文件时只能读取到一个文件。
uri string
要上传文件资源的路径
file any
要上传的文件对象
header UTSJSONObject null
HTTP 请求 Header, header 中不能设置 Referer
formData UTSJSONObject null
HTTP 请求中其他额外的 form data
timeout number 120000
超时时间,单位 ms
success (result: UploadFileSuccess) => void null
成功返回的回调函数
fail (result: UploadFileFail) => void null
失败的回调函数
complete (result: any) => void null
结束的回调函数(调用成功、失败都会执行)
enableHttp2 boolean
需要基础库: 2.10.4

是否开启 http2
enableProfile boolean
需要基础库: 3.5.0

是否开启 profile。iOS 和 Android 端默认开启,其他端暂不支持。开启后可在接口回调的 res.profile 中查看性能调试信息。
enableQuic boolean
需要基础库: 2.10.4

是否开启 Quic/h3 协议(iOS 微信目前使用 gQUIC-Q43;Android 微信在 v8.0.54 前使用 gQUIC-Q43,v8.0.54 开始使用 IETF QUIC,即 h3 协议;PC微信使用 IETF QUIC,即 h3 协议)

# UploadFileSuccess 的属性值

名称 类型 必备 兼容性 描述
data string
开发者服务器返回的数据
statusCode number
开发者服务器返回的 HTTP 状态码
profile UploadFileSuccessProfile
需要基础库: 3.5.0

网络请求过程中一些调试信息,查看详细说明。目前 iOS 和 Android 端支持。
名称 类型 必备 兼容性 描述
SSLconnectionEnd number
SSL建立完成的时间,如果不是安全连接,则值为 0
SSLconnectionStart number
SSL建立连接的时间,如果不是安全连接,则值为 0
connectEnd number
HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等。注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接完成的时间。注意这里握手结束,包括安全连接建立完成、SOCKS 授权通过
connectStart number
HTTP(TCP) 开始建立连接的时间,如果是持久连接,则与 fetchStart 值相等。注意如果在传输层发生了错误且重新建立连接,则这里显示的是新建立的连接开始的时间
domainLookUpEnd number
Local DNS 域名查询完成的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
domainLookUpStart number
Local DNS 域名查询开始的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
downstreamThroughputKbpsEstimate number
评估当前网络下载的kbps
estimate_nettype number
评估的网络状态 unknown, offline, slow 2g, 2g, 3g, 4g, last/0, 1, 2, 3, 4, 5, 6
fetchStart number
组件准备好使用 HTTP 请求抓取资源的时间,这发生在检查本地缓存之前
httpDNSDomainLookUpEnd number
需要基础库: 3.8.9

httpDNS 完成查询的时间。仅当开启 httpDNS 功能时返回该字段。目前仅wx.request接口支持
httpDNSDomainLookUpStart number
需要基础库: 3.8.9

httpDNS 开始查询的时间。仅当开启 httpDNS 功能时返回该字段。目前仅wx.request接口支持
httpRttEstimate number
协议层根据多个请求评估当前网络的 rtt(仅供参考)
invokeStart number
需要基础库: 3.8.10

调用接口的时间。
peerIP string
当前请求的IP
port number
当前请求的端口
protocol string
使用协议类型,有效值:http1.1, h2, quic, unknown
queueEnd number
需要基础库: 3.8.10

结束排队的时间。达到并行上限时才需要排队。如果未发生排队,则该字段和 queueStart 字段值相同
queueStart number
需要基础库: 3.8.10

开始排队的时间。达到并行上限时才需要排队。
receivedBytedCount number
收到字节数
redirectEnd number
最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内部的重定向才算,否则值为 0
redirectStart number
第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0
requestEnd number
HTTP请求读取真实文档结束的时间
requestStart number
HTTP请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存。连接错误重连时,这里显示的也是新建立连接的时间
responseEnd number
HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存
responseStart number
HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存
rtt number
当次请求连接过程中实时 rtt
sendBytesCount number
发送的字节数
socketReused boolean
是否复用连接
throughputKbps number
当前网络的实际下载kbps
transportRttEstimate number
传输层根据多个请求评估的当前网络的 rtt(仅供参考)
usingHighPerformanceMode boolean
是否走到了高性能模式。基础库 v3.3.4 起支持。

# UploadFileFail 的属性值

名称 类型 必备 描述
errCode number 错误码
合法值 描述
5 接口超时
1000 服务端系统错误
100001 json数据解析错误
100002 错误信息json解析失败
100003 json解析类型转换失败
600003 网络中断
600008 data参数类型不合法
600009 URL格式不合法
600010 Cronet模块加载失败
602001 request系统错误
errSubject string 统一错误主题(模块)名称
data any 错误信息中包含的数据
cause Error 源错误信息,可以包含多个错误,详见SourceError
errMsg string

# 返回值

类型
UploadTask

# UploadTask 的方法

# abort(): void,

abort 中断上传任务。

# abort 兼容性 ?
Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.91 4.11 4.61

# onProgressUpdate(callback: UploadFileProgressUpdateCallback): void,

onProgressUpdate 监听上传进度变化。

# onProgressUpdate 兼容性 ?
Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.91 4.11 4.61
# 参数
名称 类型 必填
callback (result: OnProgressUpdateResult) => void
# OnProgressUpdateResult 的属性值
名称 类型 必备 兼容性 描述
progress number
上传进度百分比
totalBytesSent number
已经上传的数据长度,单位 Bytes
totalBytesExpectedToSend number
预期需要上传的数据总长度,单位 Bytes

注意事项

  • 在4.25版本iOS平台增加了Task原生对象自动销毁的逻辑,即上传完成后自动释放原生的Task对象,建议开发者在complete回调中置空Task对象,例
complete: () => {
            this.task = null
          },

如不释放,在调用Task对象的方法将导致控制台报错: error: instance object does not exist: id:15

# 示例

示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见

扫码体验(手机浏览器跳转到App直达页)

示例

<template>
  <!-- #ifdef APP -->
  <scroll-view class="page-scroll-view uni-theme-root">
  <!-- #endif -->
    <view class="upload-page uni-theme-root">
      <page-head :title="data.title"></page-head>
      <view class="uni-padding-wrap uni-common-mt">
        <view class="demo">
          <image v-if="data.imageSrc" :src="data.imageSrc" class="image" mode="widthFix"></image>
          <text v-else class="uni-hello-addfile" @click="chooseImage">+ 选择图片</text>
        </view>
      </view>
    </view>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>
<script setup lang="uts">
  // #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
  import {
    testInovkeUploadFile,
    CommonOptions
  } from '@/uni_modules/test-invoke-network-api'
  // #endif

  type DataType = {
    title: string;
    imageSrc: string;
    task: UploadTask | null;
    jest_result: boolean;
  }

  const data = reactive({
    title: 'uploadFile',
    imageSrc: '',
    task: null,
    //自动化测试例专用
    jest_result: false,
  } as DataType)

  onUnload(() => {
    data.imageSrc = '';
    uni.hideLoading();
    data.task?.abort();
  })

  const chooseImage = () => {
    uni.chooseImage({
      count: 1,
      sizeType: ['compressed'],
      sourceType: ['album'],
      success: (res) => {
        console.log('chooseImage success, temp path is', res.tempFilePaths[0])
        var imageSrc = res.tempFilePaths[0]
        uni.showLoading({
          title: '上传中'
        })
        data.task = uni.uploadFile({
          url: 'https://unidemo.dcloud.net.cn/upload', //仅为示例,非真实的接口地址
          filePath: imageSrc,
          name: 'file',
          formData: {
            'user': 'test'
          },
          success: (res) => {
            console.log('uploadImage success, res is:', res)
            uni.showToast({
              title: '上传成功',
              icon: 'success',
              duration: 1000
            })
            data.imageSrc = imageSrc
          },
          fail: (err) => {
            console.log('uploadImage fail', err);
            uni.showModal({
              content: err.errMsg,
              showCancel: false
            });
          },
          complete: (res) => {
            uni.hideLoading();
            data.task = null
          }
        });
      },
      fail: (err) => {
        console.log('chooseImage fail', err)
      }
    })
  }

  //自动化测试例专用
  const jest_uploadFile = () => {
    const imageSrc = "/static/test-image/logo.png";
    uni.uploadFile({
      url: 'https://unidemo.dcloud.net.cn/upload', //仅为示例,非真实的接口地址
      filePath: imageSrc,
      name: 'file',
      formData: {
        'user': 'test'
      },
      success: () => {
        data.jest_result = true;
      },
      fail: () => {
        data.jest_result = false;
      },
    })
  }

  const jest_uploadFile_with_uni_env = () => {
    /**
     * 微信小程序只支持USER_DATA_PATH,且子目录未创建的情况下不能直接下载到子目录内
     */
    const filePath = `${uni.env.USER_DATA_PATH}/uni-app.png`
    uni.downloadFile({
      url: "https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni-app.png",
      filePath: filePath,
      success: () => {
        uni.uploadFile({
          url: 'https://unidemo.dcloud.net.cn/upload', //仅为示例,非真实的接口地址
          filePath: filePath,
          name: 'file',
          success: () => {
            data.jest_result = true;
          },
          fail: () => {
            data.jest_result = false;
          },
        })
      },
      fail: () => {
        data.jest_result = false
      }
    });
  }

  const jest_cookie_upload = (needCookie : boolean) => {
    const imageSrc = "/static/test-image/logo.png";
    uni.uploadFile({
      url: 'https://request.dcloud.net.cn/api/http/header/upload',
      filePath: imageSrc,
      name: 'file',
      success: (res : UploadFileSuccess) => {
        const responseData = JSON.parseObject(res.data)
        const errCode = responseData?.getNumber("errCode")
        if (errCode != null && errCode == 1000) {
          data.jest_result = needCookie ? false : true;
        } else {
          data.jest_result = needCookie ? true : false;
        }
      },
      fail: () => {
        data.jest_result = false;
      },
    })
  }

  const jest_set_cookie = () => {
    uni.request({
      url: "https://request.dcloud.net.cn/api/http/header/setCookie",
      method: "GET",
      timeout: 6000,
      sslVerify: false,
      withCredentials: false,
      firstIpv4: false,
      success: () => {
        jest_cookie_upload(true)
      },
      fail: () => {
        data.jest_result = false;
      },
    });
  }

  const jest_delete_cookie = () => {
    uni.request({
      url: "https://request.dcloud.net.cn/api/http/header/deleteCookie",
      method: "GET",
      timeout: 6000,
      sslVerify: false,
      withCredentials: false,
      firstIpv4: false,
      success: () => {
        jest_cookie_upload(false)
      },
      fail: () => {
        data.jest_result = false;
      },
    });
  }

  const jest_files_upload = () => {
    const imageSrc = "/static/test-image/logo.png";
    uni.uploadFile({
      url: 'https://unidemo.dcloud.net.cn/upload',
      files: [
        {
          name: "file1",
          uri: imageSrc
        } as UploadFileOptionFiles,
        {
          name: "file2",
          uri: imageSrc
        } as UploadFileOptionFiles
      ],
      success: (res : UploadFileSuccess) => {
        if (res.statusCode == 200) {
          data.jest_result = true;
        }
      },
      fail: () => {
        data.jest_result = false;
      },
    })
  }

  const jest_uts_module_invoked = () => {
    // #ifdef APP-ANDROID || APP-IOS || APP-HARMONY
    testInovkeUploadFile({
      success: (res : any) => {
        data.jest_result = true
      },
      fail: (err : any) => {
        data.jest_result = false
      }
    } as CommonOptions)
    // #endif
  }

  const jest_uploadFileWithoutFile = () => {
    const imageSrc = "/static/test-image/logo.png";
    uni.uploadFile({
      url: 'https://unidemo.dcloud.net.cn/upload', //仅为示例,非真实的接口地址
      formData: {
        'user': 'test'
      },
      success: (res) => {
        console.log("success: ",res);
        data.jest_result = true;
      },
      fail: (err) => {
        console.log("fail: ", err);
        data.jest_result = false;
      },
    })
  }

  const jest_uploadFileVerifyUA = () => {
    uni.uploadFile({
      url: 'https://request.dcloud.net.cn/api/http/header/upload',
      header:{
        "User-Agent":"custom"
      },
      formData: {
        'user': 'test'
      },
      success: (res : UploadFileSuccess) => {
        const responseData = JSON.parseObject(res.data)
        const innerData = responseData?.getJSON("data")
        const header = innerData?.getJSON("requestHeaders")
        const uas = header?.getArray("user-agent")
        if(uas != null) {
          data.jest_result = (uas.length == 1)
        }
      },
      fail: () => {
        data.jest_result = false;
      },
    })
  }

  defineExpose({
    data,
    jest_uploadFile,
    jest_uploadFile_with_uni_env,
    jest_set_cookie,
    jest_delete_cookie,
    jest_files_upload,
    jest_uts_module_invoked,
    jest_uploadFileWithoutFile,
    jest_uploadFileVerifyUA
  })
</script>

<style>
  .image {
    width: 100%;
  }

  .demo {
    background-color: var(--list-background-color, #ffffff);
    padding: 25px;
    justify-content: center;
    align-items: center;
  }

  .uni-hello-addfile {
    text-align: center;
    background-color: var(--list-background-color, #ffffff);
    padding: 25px;
    margin-top: 10px;
    font-size: 19px;
    color: var(--active-color, #808080);
  }
</style>

# 参见

# 通用类型

# GeneralCallbackResult

名称 类型 必备 描述
errMsg string 错误信息

注意

  • web端上传文件时仅能使用downloadFile、chooseImage等返回文件对象的接口的返回值作为要上传的文件