上传,处理,存储和交付用户提供的文件和图像

时间:2012-12-20 12:57:10

标签: php javascript jquery html ajax

在网络开发人员的生活中,您将不得不处理用户上传的文件和图片。

常见问题:

如何上传?

现代网络浏览器和技术允许多种方式将用户提供的文件上传到我的服务器。什么是最佳实践,我需要考虑什么?

如何处理?

上传完成后,我需要了解安全性以及文件的进一步处理

如何存储和投放?

是否有关于如何存储上传文件的最佳做法?

免责声明:我已将近30分钟的时间用于以下答案,最初的问题已被删除,因此我决定询问用户在处理用户提供的文件时可能会遇到的一般问题。看到我的回答,您可以自由地贡献并添加您的想法和经验

1 个答案:

答案 0 :(得分:25)

没有最好的"这些步骤的方式,但各种技术和库中的一系列既定方法和最佳实践,可以帮助您实现用户友好的上传,安全性和速度。

对于另一个遗憾被删除的问题,我已经写了这个小指南。

用户提供的文件或图片会在其生命周期中经历几个阶段:

  1. 上传本身
  2. validaton
  3. 存储处理(例如类型转换,调整大小,缩略图生成......)
  4. 存储
  5. 在前端交付
  6. 这将解决所有步骤并尽可能提供示例

    <强> 1。上传

    现代网络浏览器提供了几种上传文件的方法。

    最简单的方法是创建一个包含简单<input type="file" name="userFile" />标记的表单。提交表单后,文件将使用POST发送,可以使用PHP中的$_FILES superglobal进行访问

    <强> 1.1。 HTML中的简单表单

    <form action="upload.php" method="post" enctype="multipart/form-data">
        <input type="file" name="userFile1" />
        <input type="file" name="userFile2" />
        <input type="submit" value="upload files" />
    </form>
    

    提交表单时,会向upload.php发送POST请求 这种上传不是非常用户友好的。您的用户将无法看到上传的任何进展,上传多个文件将是一件痛苦的事情

    <强> 1.2。 Javascript ajax上传

    在此解决方案中,POST与javascript

    异步完成

    http://www.saaraan.com/2012/05/ajax-image-upload-with-progressbar-with-jquery-and-php

    <强> 1.3。 HTML 5上传

    现代浏览器支持HTML5,它允许使用进度条和预览非常好用户友好的上传屏幕 - 边框是您自己的创造力

    例如,我真的很喜欢这个演示:http://html5demos.com/dnd-upload

    在服务器端

    无论您决定使用哪种上传技术,上传都会以发送到您脚本的HTTP POST结束。所有进一步的处理都将在服务器上完成。

    PHP将文件复制到临时路径(upload_tmp_dir

    您可以使用ini_set在php.ini中或动态调整其他一些与上传相关的设置:http://php.net/manual/en/ini.core.php#ini.sect.file-uploads

    upload.php的

    <pre>
    <?php
    print_r( $_FILES );
    

    这是成功上传后$_FILES超级全球的样子。

    • 名称:原始名称
    • type:浏览器提供的mime-type
    • size:以字节为单位的大小
    • tmp_name:服务器上的临时文件名
    • 错误:错误代码为described here,当所有内容都为文件时为0

    每个文件都有自己的索引

    Array
    ( 
        [userFile1] => Array
        (
             [name] => i_love_ponies.png
             [type] => image/png
             [size] => 42233
             [tmp_name] => /tmp/_x123tfsdayx134
             [error] => 0
        )
        [userFile2] => Array
        (
             [name] => ponies_run_my_server.png
             [type] => image/png
             [size] => 12325
             [tmp_name] => /tmp/_x3123asdad3ssy
             [error] => 0
        )
    )
    

    一些额外的提示

    如果您期望大文件,请考虑webserver和php执行超时。如果上传需要10分钟,您就不希望用户最终出错。

    在PHP中,您可以增加max_execution_time

    <强> 2。验证

    您可能想问的问题

    我是否只允许特定文件 - 我会收到哪种文件?

    您在$_FILES数组中找到的类型由浏览器设置。如果您想确定上传了哪种类型,可以使用PHP的fileinfo extension

    此示例将检查上载本身是否成功,并将允许类型的文件写入新数组以进行进一步处理

    $allowedTypes = array(
       'image/png'
       'image/gif'
       'image/jpeg'
    );
    
    $useFiles = array();
    
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    foreach ( $_FILES as $index => $file )
    {
        if ( $file['error'] === UPLOAD_ERR_OK ) {
            $type = $finfo->file( $file['tmp_name'] );
            if ( in_array( $type, $allowedTypes ) ) {
                 $useFiles[$index] = $file;
            }
        }
    }
    

    我是否要设置最大文件大小 - 大小是多少?

    在这种情况下,您可以安全地依赖$_FILES['key']['size']值,即以字节为单位的大小。您不应该只依赖客户端设置文件大小限制

    如果谈论图片,我是想缩放还是创建缩略图 - 图像尺寸是什么?

    查看getimagesize以确定图片尺寸

    第3。处理

    在将文件保存到最终位置之前,您可能希望对其进行一些处理。 这是你可以

    的时间

    用于图像处理的公共库是gd libimagick。我个人更喜欢gd lib。这是一个更多的手动工作,但它更快,默认情况下大多数安装或附加安装简单。 Imagemagick本身拥有非常庞大的图像处理功能池

    <强> 4。存储数据

    现在是时候讨论存储了。首先是将临时文件复制到临时或最终位置的保存方式。

    您应该使用move_uploaded_file

    move_uploaded_file( $useFiles['tmp_name'], $destination );
    

    同样,没有&#34;最佳方式&#34;对于存储,这取决于您的环境,文件和使用。我会谈几个

    <强> 4.1。服务器文件系统

    这可能是存储文件最常用,最简单的方法。您可以使用已经运行的Web服务器静态地提供文件。这通常是文档根目录中的一个位置。

    为了让您的生活更轻松,您可以将文件名保存到数据库中 - 最好通过连接数据(如用户或位置)进行引用或引用。

    由于各种原因,您不应将所有文件保存到同一文件夹中。

    您必须为每个文件生成唯一名称,否则您将使用新文件覆盖现有文件。此外,通常的文件系统越来越慢,以寻求节点中不断增加的文件数量。当请求传递文件时,这将导致响应时间变慢。

    您可以将其保存到每个用户的文件夹中

    /uploaded/user-id/file.jpg
    

    如果您希望每个用户有大量文件,则可以拆分filname的校验和以获得更深层的文件夹结构

    e.g。

    $path =  $_SERVER['DOCUMENT_ROOT'] . '/uploaded/' . $userId . '/' . chunk_split( md5( $useFiles['index']['name'] ), 12, '/' );
    

    会导致

    /var/www/htdocs/uploaded/1/97e262286853/d52aa8c58eb7/f0431f03/
    

    <强> 4.2。数据库

    您可以使用blob类型将文件存储到MySQL数据库中。我一般不推荐这个

    <强> 4.3。内容分发网络

    如果您希望全球范围内有大量流量,您可能需要考虑将文件存储在像Cloudfront这样的Amazon S3 CDN上。

    S3是一种便宜,可靠的存储空间,适用于高达5TB的文件(据我所知)

    http://www.9lessons.info/2012/08/upload-files-to-amazon-s3-php.html

    您不必担心文件备份,可用的硬盘大小,传送速度等。Cloudfront在S3的顶部添加CDN图层,边缘位置遍布全球