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

标签 php javascript jquery html ajax

在Web开发人员生命中的晚期或早期,您将不得不处理用户上传的文件和图像。

常见问题:

如何上传?

现代的Web浏览器和技术允许通过多种方式将用户提供的文件上传到我的服务器。什么是最佳做法,我必须考虑什么?

如何处理?

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

如何存储和交付?

是否有关于如何存储上载文件的最佳实践?

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

最佳答案

每个步骤都没有“最佳”方法,但是各种技术和库中的一整套既定方法和最佳实践可以帮助您实现用户友好的上载,安全性和速度。

对于另一个不幸被删除的问题,我编写了这个小指南。

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

  • 上传本身
  • 有效期
  • 用于存储的处理(例如类型转换,调整大小,缩略图生成等)。
  • 存储
  • 前端侧
  • 交付

  • 这将解决所有步骤,并尽可能提供示例

    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>
    

    提交表单后,将POST请求发送到upload.php
    这种上传不是非常人性化。您的用户将看不到任何上传进度,并且上传多个文件会很痛苦

    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,HTML5允许非常漂亮且用户友好的上传蒙版以及进度条和预览-边框是您自己的创造力

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

    在服务器端

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

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

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

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

    成功上传后,这就是$_FILES超全局的外观。
  • 名称:原始名称
  • 类型:浏览器提供的mime类型
  • 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
        )
    )
    

    其他一些提示

    如果您期望大文件,请考虑Web服务器和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.处理

    在将文件保存到最终位置之前,您可能需要对其进行一些处理。
    那时候你可以
  • change image size for later displaying
  • create thumbnail
  • add watermark or branding
  • 转换为另一种类型。这里没有链接,因为这可以是任何类型,我敢肯定您找到了一种将.xxx转换为.yyy的解决方案:)

  • 用于图像处理的常见库是gd libimagick。我个人更喜欢gd lib。这是更多的手动工作,但速度更快,默认情况下大多数安装都附带该工具,或者安装起来很简单。 Imagemagick本身具有非常庞大的图像处理功能池

    4.存储数据

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

    您应该使用move_uploaded_file
    move_uploaded_file( $useFiles['tmp_name'], $destination );
    

    同样,没有“最佳存储方式”,这取决于您的环境,文件和使用情况。我会说一些

    4.1。服务器文件系统

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

    为了使您的生活更轻松,您可以将文件名保存到数据库中-最好是由诸如用户或位置之类的连接数据引用或引用。

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

    您必须为每个文件生成一个唯一的名称,否则您将用一个新文件覆盖现有文件。另外,随着节点中文件数量的增加,普通文件系统的查找速度也越来越慢。当请求传送文件时,这将导致响应时间变慢。

    您可以将其保存到每个用户的文件夹中
    /uploaded/user-id/file.jpg
    

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

    例如
    $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。内容交付网络

    如果您希望在全局范围内获得大量流量,则可能需要考虑将文件存储在CDN之类的CDN上,例如Cloudt的Amazon S3

    S3是一种便宜,可靠的存储设备,可存储高达5TB的文件(据我所知)

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

    您无需担心文件备份,可用硬盘大小,传送速度等问题。Cloudfront在S3的顶部添加CDN层,其边缘位置遍布全局

    关于php - 上传,处理,存储和交付用户提供的文件和图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13972714/

    相关文章:

    php - 返回屏幕命令的输出并使用 php 显示

    javascript - for循环中的延迟

    javascript - 无法在 asp mvc 中验证 TinyMCE

    PHP 降序排序无法按预期工作

    php - 如何获得 Asterisk 通话指标?

    php - 多平台 - 在 Facebook 上发布到好友时间线并发送邀请

    javascript - Vaadin 生成具有更改的列名称的网格

    javascript - 在 dojo 树标签中添加 HTML

    javascript - 输入折扣后如何计算总价

    c# - 访问asp :lable value which set using jquery?