Recently I was wondering why my uploaded videos won't play in a browser when accusing the url directly. I discovered that the wrong content-type was set during upload.
I traced the issue back to this peace of code.
Where getInitiateParams() overwrites the previously set content-type in $params.
https://github.com/aws/aws-sdk-php/blob/c0321509cccc20e6f0051ce9e36369e465388029/src/S3/MultipartUploadingTrait.php#L96-L111
It calls the function getSourceMimeType() from
https://github.com/aws/aws-sdk-php/blob/4da9a3b61473b378dea34c2b211cb3654ec3effb/src/S3/MultipartUploader.php#L136-L142
Which tries to figure out the content-type from the source. Since the source is a "php://temp" stream. It will return "application/octet-stream".
This forces the function getInitiateParams() to overwrite the previously set content-type in $params.
Which is annoying all files larger uploaded via MultipartUpload will have a content-type of "application/octet-stream".
I'm using Flysysteme AWS-S3_V3 Atapter to upload files but all its doing its calling the upload function on the S3Client
So there shouldn't be anything wrong with that.
Do I miss something or is is intended and if so why?
There was a pull request addressing that issue but there is not much information for it.
https://github.com/aws/aws-sdk-php/pull/1367
Hope somebody can help.
Thank You
Alex
Can you please post how you're generating the values to pass to Flysystem? Most insterested around:
Since the source is a "php://temp" stream.
Sure.
I read the file and store the content in a variable and pass it to flysysteme with a destination path, which then calls the upload function on the S3Client.
Which creates the ObjectUploader which creates the stream here
The body is then passed to the MultipartUploader which is the source.
Hope that helps.
Let me know if you need anything else.
Thanks for the added info. How is the $body value you pass to flysystem generated (file_get_contents(), fopen(), etc.)?
its a simple file_get_contents() to a path on the local drive.
Thanks @tiran133. I've confirmed this issue and have started review on the PR that attempts to fix it.
This fix was released in version 3.36.28.
Well this is still happening with me. The fix seems to no work.
This is my code
$s3->upload(...['params' => [
'CacheControl' => 'max-age=2592000',
'ContentType' => mime_content_type($file)
]]);
same problem to me.
protected function getSourceMimeType()
{
if ($uri = $this->source->getMetadata('uri'))
{
return Psr7\mimetype_from_filename($uri) ?: 'application/octet-stream';
}
}
Psr7\mimetype_from_filename($uri);
the SDK code tries to get the file extension from the URL, but if the URL did not contain extension then application/octet-stream returned, well...
so why not to get wrapper_data?
$headers = $this->source->getMetadata('wrapper_data');
then pick up the content-type from the headers, see https://www.php.net/manual/en/function.stream-get-meta-data.php
I had this similar issue. Below is how I solved it.
It's the params parameter that we need to pass with ContentType key & value.
$uploader = new MultipartUploader($s3Client, $file->getRealPath(), [
'bucket' => env('AWS_BUCKET'),
'key' => $path,
'params' => [
'ContentType' => $file->getMimeType()
]
]);
\GuzzleHttp\Promise\all($s3FileUploadPromises)->wait();
Most helpful comment
I had this similar issue. Below is how I solved it.
It's the
paramsparameter that we need to pass withContentTypekey & value.