当前位置: 首页 > 面试题库 >

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

陶宜民
2023-03-14
问题内容

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

常见问题:

如何上载?

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

我该如何处理?

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

如何储存和运送?

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

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


问题答案:

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

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

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

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

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

1.上传

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

最简单的方法是使用简单<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>

提交表单后,将向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-
上载

upload.php

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

这是$_FILES成功上传后超全局的外观。

  • 名称:原名
  • 类型:浏览器提供的mime类型
  • 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
    )
)

一些其他提示

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

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

在这种情况下,您可以放心地使用该$_FILES['key']['size']值(以字节为单位的大小)。您不应该仅仅依靠客户端设置的文件大小限制

如果谈论图像,我要缩放还是创建缩略图-图像尺寸是多少?

查看getimagesize以确定图像尺寸

3.加工

在将文件保存到最终位置之前,您可能需要对其进行一些处理。那时候你可以

  • 更改图像尺寸以便以后显示
  • 创建缩略图
  • 添加水印或品牌
  • 转换为另一种类型。这里没有链接,因为这可以是任何类型,我敢肯定您找到了一种将.xxx转换为.yyy的解决方案:)

用于图像处理的常用库是gd
lib和imagick。我个人更喜欢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上,例如带Cloudfront的Amazon
S3。

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

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

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



 类似资料:
  • 如果Kafka的一些信息没有被收回会发生什么。假设我正在同时使用消息。而一个使用者无法处理offset=20的消息,并且没有将Ack发回。但offset=21的其他消息已被消耗并返回ack。我怎么能只重放20个? 我需要将消息放入DLQ并再次消费吗?如果那里也发生故障怎么办?

  • 如何使用从辅助外部存储器提供文件? 的当前实现只处理 看来,没有办法定义一个

  • 我有一个Azure函数,当一个blob被上传到某个目录时会被触发。它处理一个zip文件。当我用Azure storage explorer将文件上传到容器时,它工作得非常好。当我通过网络API上传它时,它爆炸了。如果我下载了这个文件,它似乎已经损坏,但是,它与源文件大小相同,当我在2个文件之间进行超越比较时,它看起来是相同的(超越比较似乎可以看到zip文件的内容)。 这里是上传代码: 文件可以很好

  • 我希望能够将图像上传到服务器,优雅地处理错误和异常,并在表单中向用户显示错误消息,并且理想情况下仅使用现有的准系统Spring Boot和Thymeleaf安装。 使用示例项目gs-上载文件,我可以使用Spring Boot和Thymeleaf将文件上载到服务器。在application.properties中,我设置了和。但是,当我上传大于1MB的文件时,几个安全和验证问题没有解决。 > 可以上

  • 请帮助我完成使用Apache Camel和ActiveMQ的异步交付支持的体系结构,下面我已经逐个解释了我的需求。 > 我有Jetty服务器接收传入消息,并有ActiveMQ使用Kaha DB将其存储在磁盘中。 活动MQ将ack存储在kaha DB中后发送回客户端。 我有Spring AbstractPollingMessageListenerContainer JMS消息监听器,它每隔1秒从ac

  • 我正在尝试为共享文件设置文件提供程序。我的文件保存在外部存储器的“AppName”文件夹中(与Android、电影和图片文件夹的级别相同)。 以下是我的文件提供程序配置: 以及文件路径。xml: 当我试图访问我的文件: 它返回一个错误:java。lang.IllegalArgumentException:未能找到包含/storage/emulated/0/AppName/IMG_20160419_