在Android中選擇文件上傳至Tigase服務(wù)器
申請(qǐng)一個(gè)插槽
<iq from='romeo@montague.tld/garden'
id='step_03'
to='upload.montague.tld'
type='get'>
<request xmlns='urn:xmpp:http:upload:0'
filename='test.jpg'
size='23456'
content-type='image/jpeg' />
</iq>
to接收者如果沒(méi)有特殊配置則為upload.{你的domain}
必須分別包含文件名(filename)和文件大小(size)屬性,文件類型(content-type)不是必須的
服務(wù)器響應(yīng)
<iq from='upload.montague.tld'
id='step_03'
to='romeo@montague.tld/garden'
type='result'>
<slot xmlns='urn:xmpp:http:upload:0'>
<put url='https://upload.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/tr%C3%A8s%20cool.jpg'>
<header name='Authorization'>Basic Base64String==</header>
<header name='Cookie'>foo=bar; user=romeo</header>
</put>
<get url='https://download.montague.tld/4a771ac1-f0b2-4a4a-9700-f2a26fa2bb67/tr%C3%A8s%20cool.jpg' />
</slot>
</iq>
< slot > 元素中會(huì)包含上傳服務(wù)器的依賴信息
文件的上傳是通過(guò) HTTP-PUT 進(jìn)行的竿滨,超出了本文的范圍黍檩。如果 Content-Length 與槽請(qǐng)求的大小不匹配,上載服務(wù)必須拒絕文件上載。如果事先指定的 Content-Type 不匹配,則服務(wù)應(yīng)拒絕該文件。如果客戶端根本沒(méi)有指定 Content-Type,那么服務(wù)可能會(huì)將 application/octet-stream 假定為 Content-Type
<put>中的url為上傳地址
<put>中的header需要跟隨上傳的請(qǐng)求頭同時(shí)上傳
<get>中的url為下載地址
錯(cuò)誤信息
如果請(qǐng)求的文件大小過(guò)大,服務(wù)可能會(huì)響應(yīng)錯(cuò)誤芹缔,而不是向客戶機(jī)提供一個(gè)插槽。此外瓶盛,還會(huì)還會(huì)返回最大的文件大小
<iq from='upload.montague.tld'
id='step_03'
to='romeo@montague.tld/garden'
type='error'>
<request xmlns='urn:xmpp:http:upload:0'
filename='très cool.jpg'
size='23456'
content-type='image/jpeg' />
<error type='modify'>
<not-acceptable xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' />
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'>File too large. The maximum file size is 20000 bytes</text>
<file-too-large xmlns='urn:xmpp:http:upload:0'>
<max-file-size>20000</max-file-size>
</file-too-large>
</error>
</iq>
Jaxmpp使用
HttpFileUploadModule 是Jaxmpp對(duì)363的實(shí)現(xiàn)模塊
HttpFileUploadModule.findHttpUploadComponents() 如果不知道接收者最欠,可以調(diào)用該方法獲取
/**
* 文件上傳
*/
class FileUploadTask(val httpFileUploadModule: HttpFileUploadModule) : ITask {
fun requestUploadPath(contentType: String, path: String) {
val file= File(path)
httpFileUploadModule.requestUploadSlot(
JID.jidInstance(UPLOAD_HOST_NAME),
file.name,
file.length(),
contentType,
object : HttpFileUploadModule.RequestUploadSlotHandler() {
override fun onError(
responseStanza: Stanza?,
error: XMPPException.ErrorCondition?
) {
//獲取上傳路徑失敗了
}
override fun onSuccess(slot: HttpFileUploadModule.Slot?) {
//獲取上傳路徑成功
slot?.let { upload(slot,contentType,file) }
}
override fun onTimeout() {
//獲取上傳路徑超時(shí)
}
})
}
/**
* jaxmpp沒(méi)有直接支持上傳示罗,執(zhí)行自己的http工具類進(jìn)行上傳
*/
private fun upload(
slot: HttpFileUploadModule.Slot,
contentType: String,
path: File
) {
HttpUtils.uploadFile(slot, contentType, path)
}
}
上傳
/**
* 使用OkHttp作為上傳類
*/
fun uploadFile(slot: HttpFileUploadModule.Slot, contentType: String, file: File) {
val builder = Request.Builder()
val map = slot.putHeaders
map.keys.forEach {
builder.addHeader(it, map[it]!!)
}
builder.url(slot.putUri)
val body = file.asRequestBody(contentType.toMediaType())
builder.put(body)
try {
val response = http.newCall(builder.build()).execute()
LogUtils.e("上傳結(jié)果 :$response")
} catch (e: IOException) {
e.printStackTrace()
}
}