diff --git a/amazonka.cabal b/amazonka.cabal
--- a/amazonka.cabal
+++ b/amazonka.cabal
@@ -1,5 +1,5 @@
 name:                  amazonka
-version:               0.2.3
+version:               0.3.0
 synopsis:              Comprehensive Amazon Web Services SDK
 homepage:              https://github.com/brendanhay/amazonka
 license:               OtherLicense
@@ -36,24 +36,28 @@
 
     other-modules:
           Network.AWS.Internal.Auth
+        , Network.AWS.Internal.Body
         , Network.AWS.Internal.Env
         , Network.AWS.Internal.Log
         , Network.AWS.Internal.Retry
 
     build-depends:
-          amazonka-core     == 0.2.3.*
-        , base              >= 4.7     && < 5
-        , bytestring        >= 0.9
-        , conduit           >= 1.1     && < 1.3
-        , exceptions        == 0.6.*
-        , http-conduit      >= 2.1.4   && < 2.3
-        , lens              >= 4.4     && < 5
-        , mmorph            >= 1       && < 2
-        , monad-control     >= 1       && < 2
-        , mtl               >= 2.2.1   && < 2.3
-        , resourcet         >= 1.1     && < 1.3
-        , retry             >= 0.5
-        , text              >= 1.1
-        , time              >= 1.5
-        , transformers      == 0.4.*
-        , transformers-base >= 0.4.2
+          amazonka-core      == 0.3.0.*
+        , base               >= 4.7     && < 5
+        , bytestring         >= 0.9
+        , conduit            >= 1.1     && < 1.3
+        , conduit-extra      == 1.1.*
+        , cryptohash         == 0.11.*
+        , cryptohash-conduit >= 0.1.1
+        , exceptions         == 0.6.*
+        , http-conduit       >= 2.1.4   && < 2.3
+        , lens               >= 4.4     && < 5
+        , mmorph             >= 1       && < 2
+        , monad-control      >= 1       && < 2
+        , mtl                >= 2.2.1   && < 2.3
+        , resourcet          >= 1.1     && < 1.3
+        , retry              >= 0.5
+        , text               >= 1.1
+        , time               >= 1.5
+        , transformers       == 0.4.*
+        , transformers-base  >= 0.4.2
diff --git a/src/Control/Monad/Trans/AWS.hs b/src/Control/Monad/Trans/AWS.hs
--- a/src/Control/Monad/Trans/AWS.hs
+++ b/src/Control/Monad/Trans/AWS.hs
@@ -87,6 +87,12 @@
     , verify
     , verifyWith
 
+    -- ** Streaming body helpers
+    , sourceBody
+    , sourceHandle
+    , sourceFile
+    , sourceFileIO
+
     -- * Types
     , ToBuilder   (..)
     , module Network.AWS.Types
@@ -108,12 +114,13 @@
 import           Data.Conduit                 hiding (await)
 import           Data.Time
 import qualified Network.AWS                  as AWS
-import           Network.AWS.Data             (ToBuilder(..))
+import           Network.AWS.Data             (ToBuilder (..))
 import           Network.AWS.Error
 import           Network.AWS.Internal.Auth
+import           Network.AWS.Internal.Body
 import           Network.AWS.Internal.Env
+import           Network.AWS.Internal.Log     hiding (debug, info, trace)
 import qualified Network.AWS.Internal.Log     as Log
-import           Network.AWS.Internal.Log     hiding (info, debug, trace)
 import           Network.AWS.Types
 import           Network.AWS.Waiters
 import qualified Network.HTTP.Conduit         as Client
diff --git a/src/Network/AWS.hs b/src/Network/AWS.hs
--- a/src/Network/AWS.hs
+++ b/src/Network/AWS.hs
@@ -54,6 +54,12 @@
     -- * Logging
     , newLogger
 
+    -- ** Streaming body helpers
+    , sourceBody
+    , sourceHandle
+    , sourceFile
+    , sourceFileIO
+
     -- * Types
     , module Network.AWS.Types
     , module Network.AWS.Error
@@ -70,14 +76,15 @@
 import           Network.AWS.Data
 import           Network.AWS.Error
 import           Network.AWS.Internal.Auth
+import           Network.AWS.Internal.Body
 import           Network.AWS.Internal.Env
 import           Network.AWS.Internal.Log
 import           Network.AWS.Internal.Retry
 import qualified Network.AWS.Signing          as Sign
 import           Network.AWS.Types
 import           Network.AWS.Waiters
-import qualified Network.HTTP.Conduit         as Client
 import           Network.HTTP.Conduit         hiding (Request, Response)
+import qualified Network.HTTP.Conduit         as Client
 
 -- | This creates a new environment without debug logging and uses 'getAuth'
 -- to expand/discover the supplied 'Credentials'.
diff --git a/src/Network/AWS/Internal/Body.hs b/src/Network/AWS/Internal/Body.hs
new file mode 100644
--- /dev/null
+++ b/src/Network/AWS/Internal/Body.hs
@@ -0,0 +1,54 @@
+-- Module      : Network.AWS.Internal.Body
+-- Copyright   : (c) 2013-2015 Brendan Hay <brendan.g.hay@gmail.com>
+-- License     : This Source Code Form is subject to the terms of
+--               the Mozilla Public License, v. 2.0.
+--               A copy of the MPL can be found in the LICENSE file or
+--               you can obtain it at http://mozilla.org/MPL/2.0/.
+-- Maintainer  : Brendan Hay <brendan.g.hay@gmail.com>
+-- Stability   : experimental
+-- Portability : non-portable (GHC extensions)
+
+module Network.AWS.Internal.Body where
+
+import           Control.Applicative
+import           Control.Monad.IO.Class
+import           Control.Monad.Trans.Resource
+import           Crypto.Hash
+import qualified Crypto.Hash.Conduit          as Conduit
+import           Data.ByteString              (ByteString)
+import           Data.Conduit
+import qualified Data.Conduit.Binary          as Conduit
+import           Data.Int
+import           Network.AWS.Data
+import           Network.HTTP.Conduit
+import           System.IO
+
+-- | Unsafely construct a 'RqBody' from a source, manually specifying the
+-- SHA256 hash and file size.
+sourceBody :: Digest SHA256
+           -> Int64
+           -> Source (ResourceT IO) ByteString
+           -> RqBody
+sourceBody h n = RqBody h . requestBodySource n
+
+-- | Unsafely construct a 'RqBody' from a 'Handle', manually specifying the
+-- SHA256 hash and file size.
+sourceHandle :: Digest SHA256 -> Int64 -> Handle -> RqBody
+sourceHandle h n = sourceBody h n . Conduit.sourceHandle
+
+-- | Unsafely construct a 'RqBody' from a 'FilePath', manually specifying the
+-- SHA256 hash and file size.
+sourceFile :: Digest SHA256 -> Int64 -> FilePath -> RqBody
+sourceFile h n = sourceBody h n . Conduit.sourceFile
+
+-- | Safely construct a 'RqBody' from a 'FilePath', calculating the SHA256 hash
+-- and file size.
+--
+-- /Note:/ While this function will perform in constant space, it will read the
+-- entirety of the file contents _twice_. Firstly to calculate the SHA256 and
+-- lastly to stream the contents to the socket during sending.
+sourceFileIO :: MonadIO m => FilePath -> m RqBody
+sourceFileIO f = liftIO $ sourceFile
+    <$> runResourceT (Conduit.sourceFile f $$ Conduit.sinkHash)
+    <*> fmap fromIntegral (withBinaryFile f ReadMode hFileSize)
+    <*> pure f
