我正在尝试将 HTML5 文件对话框中的文件上传到我的 Google 文档帐户。
我为此请求使用 Google Documents List API 3.0 版,以及此链接上的说明。
查询后,我从文档列表 JSON 中收集正确的可恢复创建链接URL,并将 XML 实体发布到该链接以获取位置URL。我得到 200 OK 响应和位置 URL。
设置标题后,我向位置 URL 发出 PUT 请求以上传文件。对于这个问题,文件小于 512kb,不需要分块。
提交此 PUT 请求后,我收到 400 Bad Request(有时是 400 Invalid Request)响应,并且文件未上传。
有趣的是,如果我省略Content-Range标头,我可以上传一个小文件,但文本文件以外的文件已损坏。
我已经对内存中加载的文件和本地文件进行了二进制比较。看起来他们匹配。
要访问 API,我在带有http://www.google.com/jsapi的 Google 小工具中使用 Javascript 。
我使用 gadgets.io.makeRequest GET、POST 和 PUT 数据。鉴于我能够毫无问题地查询文档列表,因此我的授权标头和令牌似乎是正确的。
我应该采取什么步骤来解决这个问题?
样本输出
PUT /feeds/upload/create-session/default/private/full?v=3.0&convert=false&upload_id=[id]
Host: docs.google.com
X-Shindig-AuthType: oauth
Authorization: OAuth oauth_body_hash="x", opensocial_owner_id="x", opensocial_viewer_id="x", opensocial_app_id="x", opensocial_app_url="x", xoauth_signature_publickey="x", xoauth_public_key="x", oauth_version="1.0", oauth_timestamp="x", oauth_nonce="x", opensocial_container="x", oauth_token="x", oauth_consumer_key="x", oauth_signature_method="RSA-SHA1", oauth_signature="x"
Content-Length: 433
Content-Range: bytes 0-433/433
Content-Type: application/x-javascript
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.79 Safari/535.11,gzip(gfe)
X-Forwarded-For: 74.203.139.139
X-shindig-dos: on
X-Upload-Content-Length: 433
X-Upload-Content-Type: application/x-javascript
[bytes 0-433]
==== Received response 1:
HTTP/1.1 400
Cache-Control: no-cache, no-store, must-revalidate
Content-Length: 15
Content-Type: text/html; charset=UTF-8
Date: Thu, 05 Apr 2012 19:49:48 GMT
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Pragma: no-cache
Server: HTTP Upload Server Built on Apr 2 2012 11:47:06 (1333392426)
Via: HTTP/1.1 GWA
X-Google-Cache-Control: remote-fetch
Invalid Request
====
errors: 400 Error
编辑
二进制代码处理数据:
// -- File Upload functions --
function constructContent(docTitle) {
var atom = ['<?xml version=\"1.0\" encoding=\"UTF-8"?>',
'<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:docs=\"http://schemas.google.com/docs/2007\">',
'<title>' + docTitle + '</title>',
'</entry>'].join('');
return atom;
}
function writeFile(file, under512) {
var body = constructContent(file.name.toString());
var params = {};
console.log(body);
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.OAUTH;
params[gadgets.io.RequestParameters.OAUTH_SERVICE_NAME] = "google";
params[gadgets.io.RequestParameters.OAUTH_USE_TOKEN] = "always";
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
params[gadgets.io.RequestParameters.POST_DATA] = body;
params[gadgets.io.RequestParameters.HEADERS] = {
"Content-Type" : "application/atom+xml",
"Content-Length" : "359",
"X-Upload-Content-Type" : file.type.toString(),
"X-Upload-Content-Length" : file.size.toString()
};
var data;
submitRequest(resumableLink + '&convert=false', params, function(requestSuceeded, data) {
if ( data.rc == 200 ) {
console.log(data);
console.log(data.headers.location[0].toString());
if ( under512 == true ) {
continueFile(data.headers.location[0].toString(), file, ('0-' + file.size + '/' + file.size).toString(), under512, params);
}
else {
continueFile(data.headers.location[0].toString(), file, ('0-524287/' + file.size).toString(), under512, params);
}
}
});
}
// recursive
function continueFile(location, file, contentRange, under512) {
console.log('location: ' + location);
var contentLength = "0";
var reader = new FileReader();
var blob;
var start = contentRange.split('-')[0].toString();
var stop = contentRange.split('-')[1].split('/')[0].toString();
console.log(file.size);
console.log(file.type);
console.log('start: ' + start);
console.log('stop: ' + stop);
console.log(("bytes " + contentRange).toString());
console.log(contentRange);
( under512 == true ) ? contentLength = contentRange.split('/')[1].toString() : contentLength = "524288";
if ( file.webkitSlice ) {
blob = file.webkitSlice(start, stop+1);
}
else {
blob = file.mozSlice(start, stop+1);
}
reader.readAsBinaryString(blob);
reader.onloadend = function(evt) {
if ( evt.target.readyState == FileReader.DONE ) {
console.log(evt.target.result);
var b = showResult(reader);
// console.log('binary: ' + b);
var params = {};
params[gadgets.io.RequestParameters.AUTHORIZATION] = gadgets.io.AuthorizationType.OAUTH;
params[gadgets.io.RequestParameters.OAUTH_SERVICE_NAME] = "google";
params[gadgets.io.RequestParameters.OAUTH_USE_TOKEN] = "always";
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.PUT;
params[gadgets.io.RequestParameters.POST_DATA] = evt.target.result;
params[gadgets.io.RequestParameters.HEADERS] = {
"Content-Length" : (contentLength).toString(),
"Content-Type" : file.type.toString(),
"Content-Range" : ("bytes " + contentRange).toString().trim()
// "GData-Version" : "3.0"
};
submitRequest(location.toString().trim(), params, function(requestSucceeded, data) {
if ( data.rc == 308 ) {
var newStart = start + 524288;
var newEnd;
( end + 524288 > file.size ) ? newEnd = file.size : newEnd = end + 524288;
var range = (newStart + '-' + newEnd + '/' + file.size).toString().trim();
continueFile(data.headers.location.toString().trim(), file, range, under512);
}
else if ( data.rc == 201 ) {
console.log('done!');
}
else {
console.log('terrible error.');
console.log(data);
writeObj(data);
}
});
}
};
}
function uploadFile() {
var file = document.getElementById('uploads').files[0];
var under512 = false;
( file.size < 524287 ) ? under512 = true : under512 = false;
writeFile(file, under512);
}