Javascript XMLHttpRequest:使用XML和图像作为有效负载的多部分/相关POST
我正试图在Chrome扩展中向Picasa Webalbums发布一个图像(带有元数据)。请注意,如我所述,内容类型为image/xyz的常规帖子是有效的。但是,我希望包含一个描述/关键字,并使用XML和数据部分来描述 我通过HTML5文件阅读器和用户文件输入获取数据。我检索一个二进制文件 字符串使用Javascript XMLHttpRequest:使用XML和图像作为有效负载的多部分/相关POST,javascript,google-chrome-extension,xmlhttprequest,picasa,Javascript,Google Chrome Extension,Xmlhttprequest,Picasa,我正试图在Chrome扩展中向Picasa Webalbums发布一个图像(带有元数据)。请注意,如我所述,内容类型为image/xyz的常规帖子是有效的。但是,我希望包含一个描述/关键字,并使用XML和数据部分来描述 我通过HTML5文件阅读器和用户文件输入获取数据。我检索一个二进制文件 字符串使用 FileReader.readAsBinaryString(file); 假设这是FileReader加载字符串后的回调代码: function upload_to_album(binarySt
FileReader.readAsBinaryString(file);
假设这是FileReader加载字符串后的回调代码:
function upload_to_album(binaryString, filetype, albumid) {
var method = 'POST';
var url = 'http://picasaweb.google.com/data/feed/api/user/default/albumid/' + albumid;
var request = gen_multipart('Title', 'Description', binaryString, filetype);
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.setRequestHeader("GData-Version", '3.0');
xhr.setRequestHeader("Content-Type", 'multipart/related; boundary="END_OF_PART"');
xhr.setRequestHeader("MIME-version", "1.0");
// Add OAuth Token
xhr.setRequestHeader("Authorization", oauth.getAuthorizationHeader(url, method, ''));
xhr.onreadystatechange = function(data) {
if (xhr.readyState == 4) {
// .. handle response
}
};
xhr.send(request);
}
gen_multipart函数仅从输入值和XML模板生成multipart,并生成完全相同的输出(除了..二进制图像数据..),但为了完整性起见,这里是:
function gen_multipart(title, description, image, mimetype) {
var multipart = ['Media multipart posting', " \n", '--END_OF_PART', "\n",
'Content-Type: application/atom+xml',"\n","\n",
"<entry xmlns='http://www.w3.org/2005/Atom'>", '<title>', title, '</title>',
'<summary>', description, '</summary>',
'<category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/photos/2007#photo" />',
'</entry>', "\n", '--END_OF_PART', "\n",
'Content-Type:', mimetype, "\n\n",
image, "\n", '--END_OF_PART--'];
return multipart.join("");
}
我的问题是,我如何获得真正的二进制图像以将其包含在多部分中?我假设只是将它附加到xml字符串中就搞乱了它,但我似乎无法修复它
请注意,由于存在,base64不是解决方案。表示使用.send()
方法发送的数据将转换为unicode,并编码为UTF-8
建议通过API上传二进制数据。但是,由于您不仅要上载文件,还要将二进制数据包装到XML中,因此此选项没有用处
解决方案可以在的源代码中找到,我在遇到类似问题时编写了该源代码。为了防止Unicode转换,所有数据都添加到一个数组中,最后作为一个数组进行传输。传输时不涉及字节序列
以下代码是一个特定的衍生代码,基于:
您是否尝试过在没有元数据的情况下上载?正如我在文章中两次提到的,不使用元数据直接上传图像效果很好。我明确要求提供一个解决方案,用元数据发送它。很好的发现!感谢您的详细分析和解决方案:)请注意XMLHttpRequest.send(ArrayBuffer)已被弃用。您应该使用XMLHttpRequest.send(ArrayBufferView)(使用.buffer)或即将推出的XMLHttpRequest.sendAsBinary()。请参见@pduncan Use
返回uint8array
而不是返回uint8array.buffer
@RobW非常感谢您的深入回答:)
xhr.send(file) // With content-type set to file.type
function gen_multipart(title, description, image, mimetype) {
var multipart = [ "..." ].join(''); // See question for the source
var uint8array = new Uint8Array(multipart.length);
for (var i=0; i<multipart.length; i++) {
uint8array[i] = multipart.charCodeAt(i) & 0xff;
}
return uint8array.buffer; // <-- This is an ArrayBuffer object!
}
function gen_multipart(title, description, image, mimetype) {
image = new Uint8Array(image); // Wrap in view to get data
var before = ['Media ... ', 'Content-Type:', mimetype, "\n\n"].join('');
var after = '\n--END_OF_PART--';
var size = before.length + image.byteLength + after.length;
var uint8array = new Uint8Array(size);
var i = 0;
// Append the string.
for (; i<before.length; i++) {
uint8array[i] = before.charCodeAt(i) & 0xff;
}
// Append the binary data.
for (var j=0; j<image.byteLength; i++, j++) {
uint8array[i] = image[j];
}
// Append the remaining string
for (var j=0; j<after.length; i++, j++) {
uint8array[i] = after.charCodeAt(j) & 0xff;
}
return uint8array.buffer; // <-- This is an ArrayBuffer object!
}