无法生成Image Blob JSON Serializable

时间:2016-02-05 21:34:24

标签: javascript ios titanium appcelerator appcelerator-titanium

由于base64encode失败而创建的JIRA票证:https://jira.appcelerator.org/browse/TC-5876

我目前的CFG: Titanium SDK 5.1.2.GA 在iPhone iOS 9.1上进行测试

我遇到了一个客户项目中的问题,该客户需要将设备上的图像(使用相机)发送到WebService,然后在使用该应用程序的任何设备上看到(Android和iOS设备) 。 Titanium在拍照后提供了一个Ti.Blob对象(event.media)(它不是JSON可序列化的),我需要以某种方式将其发送到服务器。服务器总是响应一个JSON对象,因此这个Blob必须以某种方式JSON序列化。

我尝试了许多方法但没有成功:

1 - Base64编码Blob

var base64blob = Ti.Utils.base64encode(event.media);

不起作用,它会停止应用程序并抛出ASL超出最大大小错误。我想这个图像太大了,无法进行base64编码。

2 - 将Blob读入缓冲区

var blobStream = Ti.Stream.createStream({ source: event.media, mode: Ti.Stream.MODE_READ });
var buffer = Ti.createBuffer({ length: event.media.length });
var bytes = blobStream.read(buffer);

它可以工作,但我不知道如何将这个缓冲区保存为服务器可以在JSON对象中返回并稍后再次转换为Image Blob的内容。

服务器无法管理Ti.Blob对象或Ti.Buffer对象,因为首先,它们是Titanium对象,服务器是基于C#的,第二个是由于Ti.Blob和Ti.Buffer不是JSON可序列化,因此JSON返回不起作用。

我需要的内容基本上在下面的虚构示例中描述:

var imageBlob = event.media;
var JSONSerializableImg = imageBlob.toJSON();
sendImageToServer(JSONSerializableImg);

var imgFromServer = getImageFromServer();
var imageBlob = imgFromServer.toBlob();
var imgView = createImageView({
    image: imageBlob 
});

我希望有人可以帮助我解决任何转换方法。

感谢的

4 个答案:

答案 0 :(得分:1)

行,

这是我认为你必须做的。看看API,这是非常可行的。

1:您需要创建一个将保存BLOB的对象服务器端。

public class BlobContainer 
{
    public string fileName{get;set;}
    //... (Other properties)
    public byte[] data {get;set;}
}

2:将BLOB中的重要信息转换为二进制数组并发送到服务器。

var blobStream = Ti.Stream.createStream({ source: myBlob, mode: Ti.Stream.MODE_READ });
var newBuffer = Ti.createBuffer({ length: myBlob.length });
var bytes = blobStream.read(newBuffer);

3:然后通过Ajax请求将字节数据发送到服务器。请注意您发送的阵列有多大。将阵列分开并将其组合在另一侧可能是有利的(可能没有必要):

var dataObjects: [
    { id: 1, data: [BYTE_DATA_PART] },
    { id: 2, data: [BYTE_DATA_PART] }...
]
$.each(dataObjects, function(i,a) {
    $.ajax({ url: "BLA", data: JSON.stringify(a), dataType: "json", type: "POST",
        success: function() { //CONTINUE\\ },
        error: function() {alert("ERROR BRO"}) 
    });
});

4:然后服务器端在你的小blob容器中获取每个请求,存储在会话对象或缓存对象中,一旦你有N个N,将它们拼凑在一起并将该sucker存储在数据库中。

5:以相反的顺序检索内容。请记住它存储为byte []数据。您可能不得不愚弄它并将其存储为字符串,因为TI缓冲区创建字节的方式和c#解释字节的方式。最好的事情是反复试验。一旦你将所有部分都放回客户端。

var newBuffer = Ti.Stream.read(data, 0, data.length);
var newBlob = newBuffer.toBlob();

答案 1 :(得分:0)

要从服务器发送和接收二进制数据,最好使用Ti.Network.HTTPClient来发送和接收二进制数据。

这里有关于上传和下载文件的指南: http://docs.appcelerator.com/platform/latest/#!/guide/File_Uploads_and_Downloads

JSON isn't designed来承载二进制数据,尽管base64encoded二进制数据应该可以工作。这就是Ti.Utils.base64encode()确实是为了什么。如果您认为“ASL超出最大尺寸错误”不应该发生,请在Appcelerator JIRA上创建一张票

答案 2 :(得分:0)

我通过在服务器端创建一个专门用于上传照片的单独方法解决了这个问题。我按照下面的链接获取服务器端:

PHP code

在Titanium中,我必须像这样设置XHR的标题:

this.xhr.setRequestHeader("ContentType", "image/png"); this.xhr.setRequestHeader('enctype', 'multipart/form-data');

那就是它! 感谢所有答案。

答案 3 :(得分:-2)

我之前使用过以下方法(不是在Titanium中,而是在另一个基于Web的移动应用平台上)。

function convertToDataURLviaCanvas(url, callback, outputFormat){
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function(){
        var canvas = document.createElement('CANVAS');
        var ctx = canvas.getContext('2d');
        var dataURL;
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL(outputFormat);
        callback(dataURL);
        canvas = null; 
    };
    img.src = url;
}

convertToDataURLviaCanvas('http://example.com/image.png', function(base64Img){
    // Base64DataURL
});

我用它将base64编码的图像字符串作为JSON发送到我的后端服务器。然后在服务器上重新编码图像。它对我有用,但base64编码的字符串很大。