我需要将图像与其他数据(非常类似于带有附件的电子邮件)一起提供给服务器。 我还需要以可靠的方式做到这一点,所以我可以在失败时重试等。

服务器是WCF REST服务器,我用它做了很多其他的通信(JSON),但只是有了上传图像的新要求。

由于我使用JSON将数据发布到我的服务器 – 我在Android端使用GSON来序列化数据。

这是我到目前为止实现它的方式(其他一切都以这种方式工作,但我刚开始使用图像)

用户填写活动字段(文本数据)

用户通过相机意图拍摄一些照片。 目前我只使用1个文件来拍照

我从SDCard拍照,加载/调整它 – 在ImageView上显示并存储在byte []中

用户提交 – 我将所有数据与来自byte []的图像一起放入Java对象中

调用GSON转换器和序列化对象

将对象保存到SQLite中

AsyncTask在SQLite中查找记录,打开游标和获取文本

AsyncTask创建HttpConnection并将文本数据发布到我的服务器。

结束

现在我的问题..显然在#3 – 我用我的字节数组“爆炸”ram。 有时我甚至觉得我的Nexus S变得迟钝了。 但通过这样做 – 我避免用许多文件填充SD卡或app文件夹。 我拍照而不是抓住它。 下一张图片将覆盖前一张图片。

步骤#5很慢。 我没有在GSON上尝试自定义串行器,而不是将字节数组序列化为类似[1,-100,123,-12]的东西,我可以使用Base64获得更小的尺寸,但仍然如此。 它会很慢。 我最多可以有20张图片……

第6步没问题。 但是对于一定的大小(我试过300px图像),我开始在OpenCursor的第7步中得到错误

07-06 20:28:47.113: ERROR/CursorWindow(16292): need to grow: mSize = 1048576, size = 925630, freeSpace() = 402958, numRows = 2 07-06 20:28:47.113: ERROR/CursorWindow(16292): not growing since there are already 2 row(s), max size 1048576 07-06 20:28:47.113: ERROR/Cursor(16292): Failed allocating 925630 bytes for text/blob at 1,1

所以,这件事并不是我喜欢的。 理想情况下,我希望所有数据都以单件forms上传到服务器。

我想也许可以在SD卡上存储时间戳的图像,只在DB中存储他们的名字。 比我在发送到服务器之前处理它们。 成功之后我会删除那些图像。 这种逻辑会使SQLite架构更加复杂,但也许没有更好的方法?!

我想我正在寻找处理图像的最佳实践。 如何使用最少的内存/ CPU使用率进行操作:

拍照片

显示缩略图

调整

发送到服务器

编辑1:

目前我正在研究将整个shizang作为多部分MIME消息上传的可能性。 这需要在我的Android包中添加一些JAR。 此外,我不确定Apache代码加载图像和发送它们的效率如何(我猜比我的代码更好) http://okandroidletsgo.wordpress.com/2011/05/30/android-to-wcf-streaming-多部分二进制图像/

而且我必须处理在WCF端解析所有这些问题,因为没有办法使用内置的.NET框架。

http://antscode.blogspot.com/2009/11/parsing-multipart-form-data-in-wcf.html

如果你这么做,请告诉我!

编辑2:

MIME不好。 没有意义,因为它使用Base64序列化二进制文件是同样的事情。

没有人回答,但这是我认真的方式:

规则#1:处理图像时 – 避免使用对象/内存。 听起来很明显,但事实并非如此。 我认为将图像大小调整为800×600是可以的。 更大的东西 – 您可以考虑将其保留原样,因为可以在更大的文件上执行http流,但是当您将图像加载到内存中进行处理时很难处理OOMexception

规则#2:使用GSON时 – 使用JsonWriter填充流。 否则记忆会爆炸。 然后将该流传递给HttpClient。 JsonWriter将以块的forms写入数据,并在处理过程中发送数据。

规则#3:参见规则#2。 它适用于多个小图像。 通过这种方式,GSON将逐个序列化它们并将其输入流中。 无论如何,每个图像都将加载到内存中。

规则#4:这可能是最好的解决方案,但需要与服务器进行更多协调。 在发送到服务器的消息之前,图像逐个发送1。 他们在没有任何编码的情 这样它们就不必进行base64编码,也不必将它们加载到设备的内存中。 传输尺寸也会更小。 发送所有图像时 – 发布主要信息对象并在服务器上收集所有包。

规则#5:忘记在SQLite中存储BLOB

底线:

在没有任何大小调整的情况下发送图像的资源方面要便宜得多。 仅当Image得到大约800×600-ish时,resize才有意义

当图像变得像600×400-ish一样小时,在单个包中发送多个图像是有意义的

一旦你需要上传文件 – 开始思考各处的流。 不要将东西装入内存。