diff --git a/moto/core/models.py b/moto/core/models.py index 1597efc7b..ba4564e4a 100644 --- a/moto/core/models.py +++ b/moto/core/models.py @@ -184,6 +184,8 @@ class CallbackResponse(responses.CallbackResponse): body = None elif isinstance(request.body, six.text_type): body = six.BytesIO(six.b(request.body)) + elif hasattr(request.body, "read"): + body = six.BytesIO(request.body.read()) else: body = six.BytesIO(request.body) req = Request.from_values( diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index 363ccc02d..1d1e83478 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -1040,6 +1040,22 @@ def test_s3_object_in_public_bucket_using_multiple_presigned_urls(): assert response.status_code == 200, "Failed on req number {}".format(i) +@mock_s3 +def test_streaming_upload_from_file_to_presigned_url(): + s3 = boto3.resource("s3") + bucket = s3.Bucket("test-bucket") + bucket.create() + bucket.put_object(Body=b"ABCD", Key="file.txt") + + params = {"Bucket": "test-bucket", "Key": "file.txt"} + presigned_url = boto3.client("s3").generate_presigned_url( + "put_object", params, ExpiresIn=900 + ) + with open(__file__, "rb") as f: + response = requests.get(presigned_url, data=f) + assert response.status_code == 200 + + @mock_s3 def test_s3_object_in_private_bucket(): s3 = boto3.resource("s3")