通过Prototype Ajax调用提交二进制数据

时间:2016-07-15 08:45:54

标签: javascript ajax prototypejs filereader

我正在使用Prototype提交POST请求,而postdata包含许多字段,其中一个是来自文件的二进制数据(在这种情况下是用户选择上传的Excel电子表格。)

我使用HTML5 FileReader接口通过$query= "SELECT * FROM `table`"; $mysqliResult= $mysqli->query($query); if(get_resource_type($mysqliResult) === 'mysqli result') { } 获取文件的内容,效果很好。如果我使用FileReader.readAsBinaryString()打印字符串中的各种字符,那么它们会显示出预期的值。

但是,一旦我将此字符串数据放入一个对象(以及其他表单字段)并将其作为charCodeAt()选项传递给Prototype的parameters,数据就会损坏。某些字符值(如Ajax.Request())将替换为0x820xC2 0x82将替换为0xAC,依此类推。

我尝试使用0xC2 0xAC对字符串进行base64编码,但是window.atob()失败了,所以很明显我需要避免某种处理。

有没有人知道如何通过Prototype的InvalidCharacterError: String contains an invalid character传递二进制数据,同时还在同一请求中包含其他表单字段?

2 个答案:

答案 0 :(得分:1)

要进行ajax文件上传,您应该使用FormData对象

HttpsURLConnection con = (HttpsURLConnection) url.openConnection();

// timeouts
con.setConnectTimeout(5000);
con.setReadTimeout(5000);

con.setRequestMethod("put");
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestProperty("Content-length", String.valueOf(output.length()));
OutputStreamWriter os = new OutputStreamWriter(con.getOutputStream(), "UTF-8");
BufferedWriter writer = new BufferedWriter(os);
writer.write(output);
writer.close();
os.close();

con.connect();

int respCode = con.getResponseCode();

if(respCode == 200) {
        InputStreamReader is = new InputStreamReader(con.getInputStream());
        BufferedReader br = new BufferedReader(is);
        String input;
        String respBody = "";
        while ((input = br.readLine()) != null){
            respBody += input;
        }
        br.close();
        is.close();
        this.result = respBody;
}

使用此方法,服务器将看到请求,就好像它是由具有属性var data = new FormData(); //var data = new FormData(someForm); if all your fields is in an html form // add fields to form data.append('fieldname',fieldvalue); data.append('filefieldname',fileobject); //etc new Ajax.Request(url, { contentType: null, method: 'post', postBody: data, onSuccess: successFunction }) 的表单发送的

答案 1 :(得分:0)

这样做需要魔法和小精灵粉尘。 (好吧,不是真的)

首先,您需要将表单字段值作为URL参数而不是POST,然后使用文件内容覆盖帖子正文。例如

new Ajax.Request('/url.php?rawupload=1&id='+$F('id')+'&label='+label,
    {
        'method':'post',
        'postBody':fileobject,
        'onSuccess':function() { alert('success'); }
    });

fileobject是从文件上传输入元素

中检索的HTML5文件对象

是的,如果你有很多表单字段,它不是最优雅的解决方案。如果你有很多表单字段来构建查询字符串而不是手工完成,你也可以使用Hash#toQueryString

http://api.prototypejs.org/language/Hash/prototype/toQueryString/