views:

314

answers:

2

I have a need to store files on Amazon AWS S3, but in order to isolate the user from the AWS authentication I want to go via an ASP page on my site, which the user will be logged into. So:

The application sends the file using the Delphi Indy library TidHTTP.Put (FileStream) routine to the ASP page, along with some authentication stuff (mine, not AWS) on the querystring.

The ASP page checks the auth details and then if OK stores the file on S3 using my Amazon account.

Problem I have is: how do I access the data coming in from the Indy PUT using JScript in the ASP page and pass it on to S3. I'm OK with AWS signing, etc, it's just the nuts and bolts of connecting the two bits (the incoming request and the outgoing AWS request) ...

TIA R

+1  A: 

A HTTP PUT will store the file at the given location in the HTTP header - it "requests that the enclosed entity be stored under the supplied Request-URI".

The disadvantage with the PUT method is that if you are on a shared hosting environment it may not be available to you.

So if the web server supports PUT, the file should be available at the given location in the the (virtual) file system. The PUT request will be handled by the server and not ASP:

In the case of PUT, the web server handles the request itself: there is no room for a CGI or ASP application to step in. The only way for your application to capture a PUT is to operate on the low-level, ISAPI filter level

http://www.15seconds.com/issue/981120.htm

Are you sure you need PUT and can not use a POST, which will send the file to a URL where your ASP script can read it from the request stream?

mjustin
Are you sure about that? I have ISAPI app that handles PUT just fine.
Runner
@Runner: ISAPI <> ASP - I cited that the ISAPI filter level is the only way to capture a PUT
mjustin
A: 

OK, Ive got a bit further with this. Code at the ASP end is:

    var PostedDataSize   = Request.TotalBytes ;
    var PostedData       = Request.BinaryRead (PostedDataSize) ;

    var PostedDataStream = Server.CreateObject ("ADODB.Stream") ; 
    PostedDataStream.Open ;
    PostedDataStream.Type = 1 ;                    // binary
    PostedDataStream.Write (PostedData) ;

    Response.Write ("PostedDataStream.Size = " + PostedDataStream.Size + "<br>") ;

    var XML = AmazonAWSPUTRequest (BucketName, AWSDestinationFileID, PostedDataStream) ;
    .....

    function AmazonAWSPUTRequest (Bucket, Filename, InputStream) 

    {
    ....
    XMLHttp.open ("PUT", URL + FRequest, false) ;

    XMLHttp.setRequestHeader (....
    XMLHttp.setRequestHeader (....
    ...
    Response.Write ("InputStream.Size = " + InputStream.Size + "<br>") ;
    XMLHttp.send (InputStream)  ;     

So I use BinaryRead, write it to a binary stream. If I write out the size of the stream I get the size of the file I POST'ed from my application, so I reckon the data is in there somewhere. I then call a routine (with the stream as a parameter) which sets up the AWS authentication/signing and does a PUT.

The AWS call returns no errors and a file of the correct name is created in the right place, but it has a size of zero! InputStream.Size has a value the same as the stream parameter passed to the routine - i.e. the size of the original file.

Any ideas?

POSTSCRIPT. Found the problem. It's caught me a few times with streams, this one. When you write data to a stream, don't forget to reset the stream position back to zero before trying to read from the stream again. I.e. just before the line:

    XMLHttp.send (InputStream)  ; 

I needed to add:

   InputStream.Position = 0 ;

My thanks for the interest and suggestions.