文件上传UploadedFile的MIME类型问题

3

我正在使用Symfony2中的UploadedFile类来上传图像文件。我已经允许上传mime类型为image/jpgimage/png的图片。当我从我的系统上传一个png文件到服务器时,它的mime类型会自动更改。我知道这是更改了,因为当我执行此命令时:

file --mime-type /home/mysuer/img.png

它给了我这个:
home/myuser/img.png: image/png

但是当我上传文件并打印UploadedFile对象时,它会输出以下内容:
Array
(
    [media] => Symfony\Component\HttpFoundation\File\UploadedFile Object
        (
            [test:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 
            [originalName:Symfony\Component\HttpFoundation\File\UploadedFile:private] => img.png
            [mimeType:Symfony\Component\HttpFoundation\File\UploadedFile:private] => application/octet-stream
            [size:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 1246
            [error:Symfony\Component\HttpFoundation\File\UploadedFile:private] => 0
            [pathName:SplFileInfo:private] => /tmp/phpivgnne
            [fileName:SplFileInfo:private] => phpivgnne
        )

)

有人能建议一下出了什么问题吗?

编辑

这是我的代码:

public function postFileAction(Request $request)
{
    print_r($request->files->all());//Prints All files


    $image = $request->files->get('media');
    echo $image->getClientMimeType();exit; //Mime Type Information

    if (empty($image)) {
        throw new FileException('Invalid File, Please Select a Valid File.');
    }

    $uploader = $this->get('application.file_uploader');

    if (!$this->container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) {
        //authenticated (NON anonymous users)
        throw new InvalidParameterException('Invalid User, Please use valid credentials');
    }

    return $uploader->upload($image, $this->get('security.context')->getToken()->getUser()->getId());
}

PHPUnit测试代码

public function testPostFile()
{
    $file    = tempnam(sys_get_temp_dir(), 'upl'); // create file
    imagepng(imagecreatetruecolor(10, 10), $file); // create and write image/png to it
    $image   = new UploadedFile($file, 'new_image.png', 'image/png', 10, UPLOAD_ERR_OK);
    $crawler = $this->client->request(
            'POST', '/api/v1/files.json', array('submit' => 'Submit Form'), array('media' => $image)
    );

    $response = $this->client->getResponse();

    $this->assertJsonResponse($response);
    $this->assertContains('filename', $response->getContent());

    print_r($response->getContent());exit;

    $fileToken = json_decode($response->getContent());
    $this->assertNotEmpty($fileToken->filename);

    unlink($file);
    unset($file, $image, $crawler, $response);

    return $fileToken->filename;
}

我正在使用命令提示符中的 curl 测试我的 REST Web 服务文件上传,如下所示:

curl -X POST myapi.com/app_dev.php/api/v1/files.json --form "media=@/home/myuser/img.png"

这可能是由于请求的内容类型标头引起的。文件可能被发送为application/octet-stream,因此Symfony根据标头正确定义其MIME类型。 - Alex
有什么建议吗?如果它的头部应该添加头部Content-Type: image/png,那我该如何修复上传图像的问题? - Ashish Awasthi
好的,你能展示一下你的HTML表单吗?谢谢。 - Perroin Thibault
1
我在Stack Overflow上找到了一个关于Android MIME类型的答案:https://dev59.com/51_Va4cB1Zd3GeqPPQut。很抱歉,我无法再帮助你了... - Perroin Thibault
一个带有 .PNG 扩展名的 EXE 文件由于扩展名无效,永远不会自行执行。如果您的问题与图像有关,则此链接可能会有所帮助。https://dev59.com/wGUp5IYBdhLWcg3wPFz_ - techie_28
显示剩余8条评论
1个回答

7

最终我找到了解决方案,会在core-php和symfony2两个方面给出答案。

Core PHP(来源:http://php.net/manual/en/features.file-upload.php):

// DO NOT TRUST $_FILES['upfile']['mime'] VALUE !!
// Check MIME Type by yourself.
$finfo = new finfo(FILEINFO_MIME_TYPE);
if (false === $ext = array_search(
    $finfo->file($_FILES['upfile']['tmp_name']),
    array(
        'jpg' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
    ),
    true
)) {
    throw new RuntimeException('Invalid file format.');
}

因此,永远不要相信$_FILES['upfile']['mime'],始终使用fileinfo,这给了我线索。

对于Symfony2:

所以我开始查看我的代码,并发现我正在使用$file->getClientMimeType(),这是不好的,我们必须使用$file->getMimeType(),它使用fileinfo来获取MIME类型并提供正确的MIME类型。

getMimeType()中,使用MimeTypeGuesser实例猜测MIME类型,它使用finfo()mime_content_type()和系统二进制文件“file”(按顺序),具体取决于哪些可用。

感谢大家的帮助:D


1
谢谢你,非常感谢你帮助我并指引我走向正确的方向 :D @PerroinThibault - Ashish Awasthi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接