提交 63daa2a9 编写于 作者: Q qiang

Merge branch 'next' into dev

......@@ -29,7 +29,7 @@ App端如需要更丰富的相机拍照API(如直接调用前置摄像头)
|参数|类型|说明|
|:-|:-|:-|
|tempFilePaths|Array<String>|图片的本地文件路径列表|
|tempFiles|Array<Object>|图片的本地文件列表,每一项是一个 File 对象|
|tempFiles|Array<Object>、Array<File>|图片的本地文件列表,每一项是一个 File 对象|
**File 对象结构如下**
......@@ -38,6 +38,7 @@ App端如需要更丰富的相机拍照API(如直接调用前置摄像头)
|path|String|本地文件路径|
|size|Number|本地文件大小,单位:B|
|name|String|包含扩展名的文件名称,仅H5支持|
|type|String|文件类型,仅H5支持|
**示例**
......
......@@ -21,14 +21,15 @@
**success 返回参数说明**
|参数|说明|平台差异说明说明|
|:-|:-|:-|
|tempFilePath|选定视频的临时文件路径||
|duration|选定视频的时间长度,单位为 s|APP平台 2.1.0+、微信小程序|
|size|选定视频的数据量大小|APP平台 2.1.0+、微信小程序|
|height|返回选定视频的高|APP平台 2.1.0+、微信小程序|
|width|返回选定视频的宽|APP平台 2.1.0+、微信小程序|
|name|包含扩展名的文件名称|仅H5支持|
|参数|类型|说明|平台差异说明说明|
|:-|:-|:-|:-|
|tempFilePath|String|选定视频的临时文件路径||
|tempFile|File|选定的视频文件|仅H5(2.7.0+)支持|
|duration|Number|选定视频的时间长度,单位为 s|APP 2.1.0+、H5、微信小程序|
|size|Number|选定视频的数据量大小|APP 2.1.0+、H5、微信小程序|
|height|Number|返回选定视频的高|APP 2.1.0+、H5、微信小程序|
|width|Number|返回选定视频的宽|APP 2.1.0+、H5、微信小程序|
|name|String|包含扩展名的文件名称|仅H5支持|
**注意:**
* 文件的临时路径,在应用本次启动期间可以正常使用,如需持久保存,需在主动调用 [uni.saveFile](api/file/file?id=savefile),在应用下次启动时才能访问得到。
......
......@@ -9,8 +9,9 @@
|参数名|类型|必填|说明|平台差异说明|
|:-|:-|:-|:-|:-|
|url|String|是|开发者服务器 url||
|files|Array|否|需要上传的文件列表。**使用 files 时,filePath 和 name 不生效。**|App|
|files|Array|否|需要上传的文件列表。**使用 files 时,filePath 和 name 不生效。**|App、H5( 2.7.0+)|
|fileType|String|见平台差异说明|文件类型,image/video/audio|仅支付宝小程序,且必填。|
|file|File|否|要上传的文件对象。|仅H5(2.7.0+)支持|
|filePath|String|是|要上传文件资源的路径。||
|name|String|是|文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容||
|header|Object|否|HTTP 请求 Header, header 中不能设置 Referer。||
......@@ -33,6 +34,7 @@ files 参数是一个 file 对象的数组,file 对象的结构如下:
|参数名|类型|必填|说明|
|:-|:-|:-|:-|
|name|String|否|multipart 提交时,表单的项目名,默认为 file|
|file|File|否|要上传的文件对象,仅H5(2.7.0+)支持|
|uri|String|是|文件的本地地址|
Tip:
......
......@@ -15,6 +15,7 @@
|dataType|String|否|json |如果设为 json,会尝试对返回的数据做一次 JSON.parse||
|responseType|String|否|text |设置响应的数据类型。合法值:text、arraybuffer|App和支付宝小程序不支持|
|sslVerify|Boolean|否|true|验证 ssl 证书|仅App安卓端支持(HBuilderX 2.3.3+)|
|withCredentials|Boolean|否|false|跨域请求时是否携带凭证(cookies)|仅H5支持(HBuilderX 2.7.0+)|
|success|Function|否||收到开发者服务成功返回的回调函数||
|fail|Function|否||接口调用失败的回调函数||
|complete|Function|否||接口调用结束的回调函数(调用成功、失败都会执行)| |
......
......@@ -100,5 +100,8 @@ export const request = {
value = (value || '').toLowerCase()
params.responseType = Object.values(responseType).indexOf(value) < 0 ? responseType.TEXT : value
}
},
withCredentials: {
type: Boolean
}
}
}
......@@ -9,6 +9,9 @@ export const uploadFile = {
files: {
type: Array
},
file: {
type: File
},
filePath: {
type: String,
validator (value, params) {
......
......@@ -61,3 +61,8 @@ export function fileToUrl (file) {
files[url] = file
return url
}
export function revokeObjectURL (url) {
(window.URL || window.webkitURL).revokeObjectURL(url)
delete files[url]
}
......@@ -50,26 +50,27 @@ export function chooseImage ({
document.body.appendChild(imageInput)
imageInput.addEventListener('change', function (event) {
const tempFilePaths = []
const tempFiles = []
const fileCount = event.target.files.length
for (let i = 0; i < fileCount; i++) {
const file = event.target.files[i]
const filePath = fileToUrl(file)
tempFilePaths.push(filePath)
tempFiles.push({
path: filePath,
size: file.size,
name: file.name
let filePath
Object.defineProperty(file, 'filePath', {
get () {
filePath = filePath || fileToUrl(file)
return filePath
}
})
tempFiles.push(file)
}
invoke(callbackId, {
const res = {
errMsg: 'chooseImage:ok',
tempFilePaths: tempFilePaths,
get tempFilePaths () {
return tempFiles.map(({ filePath }) => filePath)
},
tempFiles: tempFiles
})
}
invoke(callbackId, res)
// TODO 用户取消选择时,触发 fail,目前尚未找到合适的方法。
})
......
import { fileToUrl } from 'uni-platform/helpers/file'
import { fileToUrl, revokeObjectURL } from 'uni-platform/helpers/file'
import { updateElementStyle } from 'uni-shared'
const {
......@@ -42,23 +42,30 @@ export function chooseVideo ({
videoInput.addEventListener('change', function (event) {
const file = event.target.files[0]
const filePath = fileToUrl(file)
let callbackResult = {
const callbackResult = {
errMsg: 'chooseVideo:ok',
tempFilePath: filePath,
tempFile: file,
size: file.size,
duration: 0,
width: 0,
height: 0,
name: file.name
}
let filePath
Object.defineProperty(callbackResult, 'tempFilePath', {
get () {
filePath = filePath || fileToUrl(this.tempFile)
return filePath
}
})
const video = document.createElement('video')
if (video.onloadedmetadata !== undefined) {
const filePath = fileToUrl(file)
// 尝试获取视频的宽高信息
video.onloadedmetadata = function () {
invoke(callbackId, Object.assign({}, callbackResult, {
revokeObjectURL(filePath)
invoke(callbackId, Object.assign(callbackResult, {
duration: video.duration || 0,
width: video.videoWidth || 0,
height: video.videoHeight || 0
......@@ -66,11 +73,9 @@ export function chooseVideo ({
}
// 部分浏览器(如微信内置浏览器)未播放无法触发loadedmetadata事件
setTimeout(() => {
invoke(callbackId, Object.assign({}, callbackResult, {
duration: 0,
width: 0,
height: 0
}))
video.onloadedmetadata = null
revokeObjectURL(filePath)
invoke(callbackId, callbackResult)
}, 300)
video.src = filePath
} else {
......
......@@ -45,7 +45,8 @@ export function request ({
header,
method,
dataType,
responseType
responseType,
withCredentials
}, callbackId) {
const {
invokeCallbackHandler: invoke
......@@ -143,6 +144,7 @@ export function request ({
errMsg: 'request:fail'
})
}
xhr.withCredentials = withCredentials
xhr.send(body)
return requestTask
}
......@@ -45,8 +45,10 @@ class UploadTask {
*/
export function uploadFile ({
url,
file,
filePath,
name,
files,
header,
formData
}, callbackId) {
......@@ -55,15 +57,24 @@ export function uploadFile ({
invokeCallbackHandler: invoke
} = UniServiceJSBridge
var uploadTask = new UploadTask(null, callbackId)
function upload (file) {
if (!Array.isArray(files) || !files.length) {
files = [{
name,
file,
uri: filePath
}]
}
function upload (realFiles) {
var xhr = new XMLHttpRequest()
var form = new FormData()
var timer
Object.keys(formData).forEach(key => {
form.append(key, formData[key])
})
form.append(name, file, file.name || `file-${Date.now()}`)
Object.values(files).forEach(({ name }, index) => {
const file = realFiles[index]
form.append(name || 'file', file, file.name || `file-${Date.now()}`)
})
xhr.open('POST', url)
Object.keys(header).forEach(key => {
xhr.setRequestHeader(key, header[key])
......@@ -118,13 +129,16 @@ export function uploadFile ({
}
}
urlToFile(filePath).then(upload).catch(() => {
setTimeout(() => {
invoke(callbackId, {
errMsg: 'uploadFile:fail file error'
})
}, 0)
})
Promise
.all(files.map(({ file, uri }) => file instanceof File ? Promise.resolve(file) : urlToFile(uri)))
.then(upload)
.catch(() => {
setTimeout(() => {
invoke(callbackId, {
errMsg: 'uploadFile:fail file error'
})
}, 0)
})
return uploadTask
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册