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

Mic*_*eim 4 html javascript php ajax jquery

在Web开发人员的生活中,您将不得不处理用户上传的文件和图像.

常见问题:

我如何上传?

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

我该如何处理?

上传完成后,我需要了解有关安全性和进一步处理文件的信息

我如何存储和交付?

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

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

Mic*_*eim 25

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

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

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

  1. 上传本身
  2. validaton
  3. 处理存储(例如类型转换,调整大小,生成缩略图......)
  4. 存储
  5. 在前端交付

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

1.上传

现代Web浏览器提供了几种上传文件的方法.

最简单的方法是创建一个带有简单<input type="file" name="userFile" />标记的表单.提交表单后,将使用POST发送文件,并可使用PHP中的$ _FILES 超全局访问该文件

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>
Run Code Online (Sandbox Code Playgroud)

提交表单时,会向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)

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

upload.php的

<pre>
<?php
print_r( $_FILES );
Run Code Online (Sandbox Code Playgroud)

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

  • 名称:原始名称
  • type:浏览器提供的mime-type
  • size:以字节为单位的大小
  • tmp_name:服务器上的临时文件名
  • 错误:此处描述的错误代码,当所有内容都归档时为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
    )
)
Run Code Online (Sandbox Code Playgroud)

一些额外的提示

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

在PHP中,您可以增加max_execution_time

2.验证

您可能想问的问题

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

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

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

$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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

看看getimagesize来确定图像尺寸

3.处理

在将文件保存到最终位置之前,您可能希望使用它进行一些处理.那是你可以的时间

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

4.存储您的数据

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

你应该使用move_uploaded_file

move_uploaded_file( $useFiles['tmp_name'], $destination );
Run Code Online (Sandbox Code Playgroud)

同样,存储没有"最佳方式",这取决于您的环境,文件和使用.我会谈几个

4.1.服务器文件系统

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

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

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

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

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

/uploaded/user-id/file.jpg
Run Code Online (Sandbox Code Playgroud)

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

例如

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

会导致

/var/www/htdocs/uploaded/1/97e262286853/d52aa8c58eb7/f0431f03/
Run Code Online (Sandbox Code Playgroud)

4.2.数据库

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

4.3.内容分发网络

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

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

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

您不必担心文件备份,可用的硬盘大小,交付速度等等.Cloudfront在S3 之上添加了一个CDN层,其边缘位置遍布全球