REST PUT to AWS S3 -- works on iOS, not Android
What works
We have successfully come up with the code to upload a file using a RESTful PUT to Amazon's S3 simple storage service. We have shared all of our code and required libraries at the links at the bottom of this question. Hopefully others find this helpful when uploading files from iOS to S3.
The problem
The upload does not complete successfully on the Android Simulator or an Android device. The error we get is:
InvalidArgument: Authorization header is invalid – one and only one ' ' (space) required
We have checked extremely thoroughly for extra spaces. The upload would fail on iOS as well if there were actually extra spaces in our authorization header. Yet this code works great for successfully uploading files using an iOS simulator and device.
Our Setup
Titanium SDK: 1.6.2
iOS SDK 4.3
Android SDK: APIs 2.2 Screen: HVGA
Android Device: Motorolla Droid Pro running 2.2.1
The crux of our code
xhr.open('PUT', 'https://s3.amazonaws.com/'+AWSBucketName+'/' + fileName, false);
var StringToSign = 'PUT\n\n\n'+fileContents.mimeType+'\n' + currentDateTime + '\n/'+AWSBucketName+'/' + fileName;
var AWSSignature = b64_hmac_sha1(AWSSecretAccessKey, Utf8.encode(StringToSign));
var AuthorizationHeader = AWSAccessKeyID.concat(AWSSignature);
xhr.setRequestHeader('Authorization', Ti.Utils.base64encode(AuthorizationHeader).toString());
xhr.setRequestHeader('Content-Type', fileContents.mimeType);
xhr.setRequestHeader('Host', 's3.amazonaws.com');
xhr.setRequestHeader('Date', currentDateTime);
xhr.send(fileContents);
Our complete code and libraries used
Our Complete S3Upload.js Code
http://pastie.org/1996251
SHA Library from AWS Project (save as sha-aws.js)
http://pastie.org/1996385
UTF8 Library (save as UTF8.js)
http://www.webtoolkit.info/javascript-utf8.html
Date formatting library (save as date.js)
http://www.mattkruse.com/javascript/date/source.html
10 Answers
-
I don't know about Android, but I had to really hack the original code up to make it work in iOS on SDK 2.1.2. I had to tweak the date format generated, cleaned up the building of the Authorization header (which was being generated incorrectly), and cleaned up the generation of the specific URLs.
see: https://gist.github.com/3607211
-
I'm using a the HTML POST solution… It requires 1.7 RC ~> see my gist here: https://gist.github.com/1012632, this lets me fetch a signature + policy from my web server and then send the file to s3 using a multi part form post.
-
Matthew - did you crack this eventually.
I too have iOS working fine. I can also get a small file into s3 from Android but it doesn't contain the picture. Very odd.
Anything you can share would be appreciated.
-
Ok I can confirm that after for testing the situation is this;
The code supplied in this thread does support iOS uploads but not Android (the file simply never makes it to s3 due to the fact that the 'Authorization header is invalid – one and only one ' ' (space) required' error occurs"
However if you comment out the authorization header iOS still uploads the full file and Android uploads a very small 15 byte file, but no actual image behind it. Very, very odd.
Does that happen to you Sam?
-
Just to add more to this it appears that SDK 1.8.2 has issues uploading images when using httpclient.
Guess I'll just have to wait for the latest SDK upgrade - hopefully 1.9.
-
Hi,
Even am facing the same and authentication problem too, did you people get authentication if so can you please help me out, for iphone it shows as authenticated user but file dosent get uploaded until we change settings as for "All users" in aws in andorid also same issue but it throws" one and only one space required" error for authentication
-
Is authentication working for you if so can you please help me out,
In iphone it says your file is uploaded but if check on s3 its not getting
uploaded until i change s3 settings to ALL Users and in android it is throwing " one
and only one space required" error. If your done with authentication please help me out.Thank You
-
I have a defect file with Appcelerator with regards to the people having issues with Android uploading 15 bytes instead of an image. See here:
https://jira.appcelerator.org/browse/TIMOB-9590
-
This bug was fixed on Tuesday (Aug 14th). Can someone download the nightly build and see if it's fixed?
-
Has anyone got this to work?
https://jira.appcelerator.org/browse/TIMOB-9590 says it is resolved as of release 3.0.0, but I am using Titanium Studio, build: 3.4.1.201410281727 and I am still getting this issue. I am using the same segment of code as shown in the test case in the PR, except with my own filenames, URLs, etc. It works on iOS simulator but not my Android device. I get the following error message:
InvalidArgument: Authorization header is invalid – one and only one ' ' (space) required
I'm wondering if maybe this problem started to happen again because of something in the recent builds? My version of Titanium is apparently either reading "[object TiBlob]" instead of the actual image data when I do
fileContents = uploadFile.read();
or it is just not sending the actual image data when I later doxhr.send(fileContents);
What should I do?