转载地址:http://www.longdw.com/ionic2-imagepicker-multiple-file-upload/
最近在研究的ionic2,准备公司项目用该框架来写。近期在做多附件上传时遇到问题了,先简单的说下自己所遇到的具体问题和解决方案。另外强调下,由于web这块之前是一窍不通,经过一段时间的学习从最简单的html、css、javascript接着angularjs2再到ionic2,也算是入门了,web需要探究和摸索的地方实在是太多了,但好在ionic2封装了项目开发过程中绝大多数常见的控件和功能,所以对于我这种菜鸟来说开发起来不至于摸不着头脑。
UI部分并不难,但是在附件上传这块卡手至少一个星期,其实一直到今天完成该功能回头想想还是当初想的太复杂了些。找了很多资料,由于ionic2出来也没多久,百度资料很少,只能去谷歌,其中一个解决方案就是使用native中提供的Transfer插件。本来还挺高兴的,心想终于找到答案了,但是看过文档后才发现该插件只支持单个文件的上传,想要实现多附件?不好意思,我是没想到办法,后来找到一哥们写的放在for循环里面,显然不行,这会导致上传完后在服务端出现多条记录(相当于post了很多次)。没辙,又在stackoverflow上用我那蹩脚的英语提问了,万能的S.O也没能帮到我。
经过了长达数天的煎熬,到处找资料,也稍微有点头绪了,但是web这块实在是菜,看了很多资料也就激发出一点点灵感,大概意思是使用window.resolveLocalFileSystemURL方法将本地选取的图片转为Blob然后追加到FormData中去,但是怎么upload也没说啊。最重要的是ts文件中window.resolveLocalFileSystemURL这个方法根本就不存在,后来找到了替代的方法File.resolveLocalFilesystemUrl,但是不管怎么转都是报错。再后来就是发现了这篇让我脱离苦海的文章,经过一番调试后发现,ImagePicker中返回的URI和这篇文章中使用的Camera返回的URI不一样,少了个file://,后来把这串加上后终于可以了。然后就是见证奇迹的时刻。
下面附上代码节选,几天的精华都在这里面了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
private
upload
(
filePaths
:
Array
<
string
>
)
:
Observable
<
any
>
{
//每个文件上传任务创建一个信号
var
observables:
Array
<
any
>
=
[
]
;
filePaths
.
forEach
(
(
value
:
string
,
i
,
array
)
=
>
{
if
(
!
value
.
startsWith
(
'file://'
)
)
{
value
=
'file://'
+
value
;
}
console
.
log
(
'这里应该执行了吧.........'
)
;
var
observable
=
new
Observable
(
(
sub
:
any
)
=
>
{
File
.
resolveLocalFilesystemUrl
(
value
)
.
then
(
entry
=
>
{
(
<
FileEntry
>
entry
)
.
file
(
file
=
>
{
// this.readFile(<Blob>file);
let
blob
:
Blob
=
<
Blob
>
file
;
const
reader
=
new
FileReader
(
)
;
reader
.
onloadend
=
(
)
=
>
{
const
imgBlob
=
new
Blob
(
[
reader
.
result
]
,
{
type
:
blob
.
type
}
)
;
this
.
formData
.
append
(
'file'
,
imgBlob
,
(
<
any
>
blob
)
.
name
)
;
console
.
log
(
'已经成功一半了.................'
+
+
imgBlob
)
;
sub
.
next
(
null
)
;
sub
.
complete
(
)
;
}
;
reader
.
readAsArrayBuffer
(
blob
)
;
}
)
;
}
)
.
catch
(
error
=
>
console
.
log
(
'报错了,日了狗----->'
+
JSON
.
stringify
(
error
)
)
)
;
}
)
;
observables
.
push
(
observable
)
;
}
)
;
return
ForkJoinObservable
.
create
(
observables
)
;
}
uploadFile
(
host
:
string
,
params
:
Map
<
string
,
string
>
,
filePaths
:
Array
<
string
>
,
context
:
any
,
success
:
Function
,
fail
:
Function
)
{
this
.
formData
=
new
FormData
(
)
;
this
.
upload
(
filePaths
)
.
subscribe
(
data
=
>
{
console
.
log
(
'开始上传........'
)
;
params
.
forEach
(
(
value
,
key
)
=
>
{
this
.
formData
.
append
(
key
,
value
)
;
}
)
;
this
.
http
.
post
(
host
,
this
.
formData
)
.
toPromise
(
)
.
then
(
res
=
>
{
success
.
call
(
context
,
res
)
;
}
)
.
catch
(
error
=
>
{
fail
.
call
(
context
,
error
)
;
}
)
;
// .catch(e => this.handleError(e))
// .map(response => response.text())
// // .finally(() => console.log('完成了'))
// .subscribe(ok => console.log('上传成功了'));
}
,
error
=
>
{
console
.
log
(
'文件处理失败'
)
;
}
)
;
}
|
可以这么去调用:
1
2
3
4
5
|
this
.
fileUpload
.
uploadFile
(
this
.
host
,
this
.
params
,
images
,
self
,
res
=
>
{
console
.
log
(
'真的可以了'
)
;
}
,
error
=
>
{
console
.
log
(
'好像失败了'
)
;
}
)
;
|
当然别忘了引入相关的包
1
2
3
4
5
6
7
8
9
|
import
{
Http
,
Response
,
Headers
,
RequestOptions
}
from
'@angular/http'
;
import
{
Observable
}
from
'rxjs/Observable'
;
import
{
ForkJoinObservable
}
from
"rxjs/observable/ForkJoinObservable"
;
import
{
File
,
Entry
,
FileEntry
}
from
'ionic-native'
;
import
'rxjs/add/operator/map'
;
import
'rxjs/add/operator/catch'
;
import
'rxjs/add/operator/map'
;
import
'rxjs/add/operator/toPromise'
;
|