Javascript 使用请求对象上载图像文件

Javascript 使用请求对象上载图像文件,javascript,file-upload,request,firefox-addon-sdk,Javascript,File Upload,Request,Firefox Addon Sdk,在我目前开发的Firefox扩展中,我已经尝试使用Firefox插件SDK的request模块将图像文件上传到服务器上好几天了。 我设法上传了一个文本文件,但我不能上传任何其他类型的文件。 我的最终目标是上传一个截图,所以我真的需要能够上传一个图像。 这是我目前的代码: params=file.read(“C:\\FullPath\h3nf5v2c.png”,“b”); //多部分表单数据 边界=“------------------------------------1326110195325

在我目前开发的Firefox扩展中,我已经尝试使用Firefox插件SDK的
request
模块将图像文件上传到服务器上好几天了。 我设法上传了一个文本文件,但我不能上传任何其他类型的文件。 我的最终目标是上传一个截图,所以我真的需要能够上传一个图像。 这是我目前的代码:

params=file.read(“C:\\FullPath\h3nf5v2c.png”,“b”);
//多部分表单数据
边界=“------------------------------------132611019532525”;
var snapShotUpload=请求({
url:“https://myurl.com",
标题:{
“推荐人”:https://myurl.com",
“内容类型”:“多部分/表单数据;边界=“+boundary,
},
内容:“--”+boundary+”\r\n“+”内容处理:表单数据;name='Upload_FileName';FileName='h3nf5v2c.png'\r\n内容类型:应用程序/八位字节流\r\n\r\n“+params+”\r\n--“+boundary+”--\r\n”,
未完成:功能(响应){
console.log(response.text);
}                        
});
console.log(“生成请求”);
snapShotUpload.post();
上传的图像已损坏,我无法读取

所以我的问题是:

如何使用Firefox附加SDK的
请求
模块发布图像?

不幸的是,答案是:你不能。
请求
模块主要用于传输url编码的数据,因此任何非字符串的内容都被假定为包含需要编码的键值对的对象。因此,如果您需要发送多部分内容,那么发送字符串是您唯一的选择。
XMLHttpRequest
将始终将字符串编码为UTF-8,这将在您尝试发送原始二进制数据(例如图像数据)时产生不希望的结果

这样做会容易得多,但即使您创建了一个请求,
请求
模块也不会将其传递给
XMLHttpRequest
。除了修改
request
模块(附加SDK的文件
packages/addon kit/lib/request.js
),没有简单的解决方案。找到这一行:

let data=stringify(内容);
将其更改为以下代码应该有效:

let{Ci}=require(“chrome”);
让数据=内容;
if(!(Ci.nsIDOMFormData的内容实例))
数据=字符串化(内容);
这样可以确保
FormData
对象不会更改

请注意,
main.js
中可能没有定义
FormData
File
。如果是这种情况,那么从任何JavaScript模块中“窃取”它们应该是可行的:

let{Cu}=require(“chrome”);
var{FormData,File}=Cu.import(“resource://gre/modules/Services.jsm")

我认为还有另一种方法可以在服务器上发布图像。您可以使用base64编码。 我从未测试过它,但我在网上找到了解释如何转换图像的方法。我希望这能对你有所帮助。

谢谢你,瓦拉迪米尔

我实际上没有修改请求模块,只是使用了XMLHttpRequest。 如果有人感兴趣,下面是我使用的代码:

function sendImage(file){
        fName = "h3nf5v2c.png";

    // prepare the MIME POST data
    var boundaryString = '---------------------------132611019532525';
    var boundary = '--' + boundaryString;
    var requestbody = boundary + '\r\n'
            + 'Content-Disposition: form-data; name="Upload_FileName"; filename="'
            + fName + '"' + '\r\n'
            + 'Content-Type: image/png' + '\r\n'
            + '\r\n'
            + file.read()
            + '\r\n'
            + boundary + '--\r\n';

    // Send
    var http_request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
            .createInstance(Components.interfaces.nsIXMLHttpRequest);

    http_request.onreadystatechange = function() {
        if (http_request.readyState == 4 && http_request.status == 200) {
            console.log(http_request.responseText);
        }
    };

    http_request.open('POST', 'http://myUrl.com', true);
    http_request.setRequestHeader("Referer", "http://myUrl.com");                  
    http_request.setRequestHeader("Content-type", "multipart/form-data; boundary=" + boundaryString);
    //http_request.setRequestHeader("Connection", "close");
    http_request.setRequestHeader("Content-length", requestbody.length);
    http_request.sendAsBinary(requestbody);    

}
函数的file参数是文件模块中的文件对象

最后的sendAsBinary函数非常重要,因为我只在客户端工作,必须通过表单模拟插入。
如果您可以访问服务器端,则发送base64编码版本的图像并在服务器端对其进行解码可能会更简单。

可以简化您的生活的是将FormData和XMLHttpRequests一起使用,如本例所示

function uploadFiles(url, files) {
    var formData = new FormData();
    for (var i = 0, file; file = files[i]; ++i) {
        formData.append(file.name, file);
    }

    var xhr = new XMLHttpRequest();
    xhr.open('POST', url, true);
    xhr.onload = function(e) { ... };

    xhr.send(formData);  // multipart/form-data
}

document.querySelector('input[type="file"]').addEventListener('change', function(e) {
    uploadFiles('/server', this.files);
}, false);

来源:

是的,我已经想到了,但我没有工作,我的服务器只接受二进制文件。但我要试试帕兰特先生的技巧。谢谢这行不通,具有二进制内容的文件对象没有默认的.toString()生成器。好的,我的文件参数实际上是一个file.read()。我编辑了我的解决方案。谢谢