/*
* Copyright 2010-2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
using Amazon.Runtime;
using Amazon.S3.Util;
using Amazon.Util;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
namespace Amazon.S3.Model
{
///
/// Parameters for uploading to Amazon S3 a file using HTTP POST
///
///
///
/// If a S3PostUploadSignedPolicy is assigned, then values set (other than InputStream or Path) on this object must adhere to the policy.
/// This includes metadata. If metadata is specified in the policy, then it must be included in the request. Adding metadata not in the
/// policy will cause the POST to fail.
///
/// For more information,
///
///
public class PostObjectRequest : AmazonWebServiceRequest
{
private S3StorageClass _storageClass;
private HttpStatusCode _actionStatus;
private RegionEndpoint _region = RegionEndpoint.USEast1;
private bool
_isSetStorageClass = false,
_isSetActionStatus = false;
///
/// Upload data to Amazon S3 using HTTP POST.
///
///
/// For more information,
///
public PostObjectRequest()
{
this.Metadata = new Dictionary();
this.CannedACL = S3CannedACL.Private;
this._actionStatus = HttpStatusCode.NoContent;
this._storageClass = S3StorageClass.Standard;
}
///
/// S3 Bucket to upload the object to
///
public string Bucket { get; set; }
///
/// The name of the uploaded key.
///
public string Key { get; set; }
///
/// Stream to read the upload data for
///
///
/// If you use InputStream, then you also need to set ContentLength
///
public Stream InputStream { get; set; }
///
/// File path to read the upload data from
///
public string Path { get; set; }
///
/// Content type for the uploaded data
///
///
/// This API is deprecated. We recommend that you use Headers.ContentType instead.
///
[Obsolete("This API is deprecated. We recommend that you use Headers.ContentType instead.")]
public string ContentType { get { return Headers.ContentType; } set { Headers.ContentType = value; } }
///
/// Specifies an Amazon S3 access control list
///
public S3CannedACL CannedACL { get; set; }
///
/// Signed policy from bucket owner.
///
public S3PostUploadSignedPolicy SignedPolicy { get; set; }
///
/// Where to redirect browsers on a successful upload
///
public string SuccessActionRedirect { get; set; }
///
/// The status code returned to the client upon successful upload if success_action_redirect is not specified
///
///
///
/// Accepts the values OK (200) , Created (201), or NoContent (204, default).
///
/// If the value is set to OK or NoContent, Amazon S3 returns an empty document with a 200 or 204 status code.
///
/// If the value is set to Created, Amazon S3 returns an XML document with a 201 status code.
///
/// If the value is not set or if it is set to an invalid value, Amazon S3 returns an empty document with a 204 status code.
///
///
public HttpStatusCode SuccessActionStatus
{
get { return this._actionStatus; }
set
{
this._actionStatus = value;
this._isSetActionStatus = true;
}
}
///
/// Storage class to use for storing the object
///
///
/// Default: STANDARD
///
public S3StorageClass StorageClass
{
get { return this._storageClass; }
set
{
this._storageClass = value;
this._isSetStorageClass = true;
}
}
///
/// The AWS region where the bucket is located.
///
///
/// Depending upon the bucket name, POST uploads will be
/// successfully redirected, but for buckets with non-DNS-compliant
/// characters, redirects will fail. Setting this to the appropriate
/// region will avoid the redirect.
///
public RegionEndpoint Region
{
get { return this._region; }
set { this._region = value; }
}
///
/// Metadata to set on the uploaded object
///
///
/// If keys do not begin with 'x-amz-meta-' it will be added at POST time.
///
public IDictionary Metadata { get; set; }
private HeadersCollectionPost headersCollection = new HeadersCollectionPost();
///
/// The collection of headers for the request.
///
public HeadersCollectionPost Headers
{
get
{
if (this.headersCollection == null)
this.headersCollection = new HeadersCollectionPost();
return this.headersCollection;
}
internal set
{
this.headersCollection = value;
}
}
///
/// Attach a callback that will be called as data is being sent to the AWS Service.
///
public EventHandler StreamTransferProgress
{
get
{
return ((Amazon.Runtime.Internal.IAmazonWebServiceRequest)this).StreamUploadProgressCallback;
}
set
{
((Amazon.Runtime.Internal.IAmazonWebServiceRequest)this).StreamUploadProgressCallback = value;
}
}
///
/// Write the multipart/form-data for this request for all fields except the file data to a stream
///
internal void WriteFormData(string boundary, Stream outputStream)
{
if (!String.IsNullOrEmpty(this.Key))
WriteFormDatum(outputStream, S3Constants.PostFormDataObjectKey, this.Key, boundary);
WriteFormDatum(outputStream, S3Constants.PostFormDataAcl, this.CannedACL, boundary);
if (this._isSetStorageClass)
WriteFormDatum(outputStream, HeaderKeys.XAmzStorageClassHeader, this.StorageClass, boundary);
if (this._isSetActionStatus)
WriteFormDatum(outputStream, S3Constants.PostFormDataStatus, ((Int32)this.SuccessActionStatus).ToString(CultureInfo.InvariantCulture), boundary);
if (!String.IsNullOrEmpty(this.SuccessActionRedirect))
WriteFormDatum(outputStream, S3Constants.PostFormDataRedirect, this.SuccessActionRedirect, boundary);
if (this.SignedPolicy != null && !string.IsNullOrEmpty(this.SignedPolicy.SecurityToken))
{
this.Metadata[S3Constants.PostFormDataSecurityToken] = this.SignedPolicy.SecurityToken;
}
foreach (var key in this.Headers.Keys)
{
if (!String.IsNullOrEmpty(this.Headers[key]))
WriteFormDatum(outputStream, key, this.Headers[key], boundary);
}
foreach (var kvp in this.Metadata)
{
var metakey = kvp.Key.StartsWith(S3Constants.PostFormDataXAmzPrefix, StringComparison.Ordinal) ? kvp.Key : S3Constants.PostFormDataMetaPrefix + kvp.Key;
WriteFormDatum(outputStream, metakey, kvp.Value, boundary);
}
if (this.SignedPolicy != null)
{
if (this.SignedPolicy.SignatureVersion == "2")
{
WriteFormDatum(outputStream, S3Constants.PostFormDataPolicy, this.SignedPolicy.Policy, boundary);
WriteFormDatum(outputStream, S3Constants.PostFormDataSignature, this.SignedPolicy.Signature, boundary);
WriteFormDatum(outputStream, S3Constants.PostFormDataAccessKeyId, this.SignedPolicy.AccessKeyId, boundary);
}
else
{
WriteFormDatum(outputStream, S3Constants.PostFormDataPolicy, this.SignedPolicy.Policy, boundary);
WriteFormDatum(outputStream, S3Constants.PostFormDataXAmzSignature, this.SignedPolicy.Signature, boundary);
WriteFormDatum(outputStream, S3Constants.PostFormDataXAmzAlgorithm, this.SignedPolicy.Algorithm, boundary);
WriteFormDatum(outputStream, S3Constants.PostFormDataXAmzCredential, this.SignedPolicy.Credential, boundary);
WriteFormDatum(outputStream, S3Constants.PostFormDataXAmzDate, this.SignedPolicy.Date, boundary);
}
}
}
private static void WriteFormDatum(Stream stream, string name, string value, string boundary)
{
byte[] bytes = Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, name, value));
stream.Write(bytes, 0, bytes.Length);
}
}
}