【问题标题】:Make sure all files are uploaded to web server确保所有文件都上传到 Web 服务器
【发布时间】:2016-01-21 22:20:02
【问题描述】:

我有一个需要上传的文件列表,每个文件都在单独的请求中上传。我如何确保每个文件都成功上传,如果有任何失败,它们都失败了?我用来上传文件的代码是:

for (var i = 0; i < files.length; i++) {
  upload(files[i]).then(function(d) {
    // success
    ...
  }).catch(function(d) {
    // fail
    ...  
  });
}

服务器接收每个文件并将其保存在文件夹下。我想确保我发送的每个文件都成功上传,如果没有删除服务器上的所有文件。

【问题讨论】:

  • 您需要告诉您的服务器总数以及您正在上传总数中的哪一项,然后服务器可以决定是否需要删除或移动。如果你有一个密封的上传例程,你可以在上传 POST 上添加一个 GET 参数。
  • 服务器将同时处理它从许多用户那里获得的每个请求,那么服务器如何知道一切都成功了。例如,假设我上传了 3 个文件,并告诉服务器我要上传 3 个文件。如果只上传了 2 个文件,服务器将等待第三个文件,即使它失败(例如用户断开连接)。
  • 它可以等待,使用缓冲区刷新或其他东西,但这是一个好点。如果服务器被告知 3/3,则很容易检查问题,并且 temp 文件夹中只有一个文件,但如果它被放弃,事情就会变得模糊不清。删除任何超过 1 小时的文件的简单 chron 作业应该涵盖您。

标签: javascript file-upload server


【解决方案1】:

由于您单独上传每个文件,因此您的服务器无法知道它们是否全部成功。

您可以做的是在每次上传时通知您的服务器以获取下一个文件。 通过这样做,您可以在服务器端(在会话/数据库/临时文件上)保留一个列表,其中包含已上传的文件和下一个文件。

如果上传的文件有问题(之前的上传通知了下一个不同的文件),那么服务器应该中止上传和回滚(根据您保存的列表删除文件)并返回错误给客户。

为了使其正常工作,唯一剩下的就是注意最后 K 个文件上传失败的情况。在这种情况下,服务器无法自行回滚,因此您必须通知它手动回滚。您可以通过在 catch 代码上创建一个新请求来做到这一点。像以前一样,当服务器被告知它必须回滚时,它应该开始从您的临时列表中删除文件并向您的客户端响应错误。

如果客户端断开连接并且无法将请求发送到服务器,那么您唯一的解决方案是使用 cron 作业

【讨论】:

    【解决方案2】:

    实际上有一个完美的手工制作的 PHP 函数 - file_exists('filename'),它根据 'filename' 是否存在返回 true 或 false。如果您的文件被远程存储,则必须包含从根目录到文件的路径,因此在您的情况下,它将是 file_exists('files/filename')。要一次检查所有文件,只需使用另一个结合一些 if 语句的 for 循环(以下假设 PHP 和可预测的文件名):

    $numOfFiles = numOfFiles;
    $fileChecker;
    $fileKiller;
    $safeFiles = 0;
    
    for ($fileChecker = 0; $fileChecker < $numOfFiles; $fileChecker += 1) {
        if (file_exists('files/file' . $fileChecker)) {
            $safeFiles += 1
        }
    }
    
    if ($safeFiles < $numOfFiles or intval(date('i')) % 60 === 0) {
        for ($fileKiller = 0; $fileKiller < $safeFiles; $fileKiller += 1) {
            unlink('files/file' . $fileKiller);
        }
    }
    

    基本上,这需要您上传的文件数(假设它是已知的),并运行一个 for 循环来验证 file[n] 是否存在。对于每个具有可验证存在的文件,计数器 ($safeFiles) 都会加一。

    如果安全文件的数量小于文件的数量,或者时间正好可以被 60 整除(表示小时标记),则上传的文件将通过另一个 for 循环逐步删除,这个使用 $safeFiles 作为上限。删除本身是通过 unlink() 销毁文件引用而发生的。

    使用 unlink() 函数有一些陷阱,详见here;确保将目标数据限制在一个文件夹中,以便您必须删除尽可能少的引用。一旦数据离开它的盒子,您可能会有更多的删除引用,并且随着您删除越来越多的单个文件实例,该函数可能会变得越来越长。

    intval(date('i')) 以分钟为单位返回时间;当它可以被 60 整除时,时间正好是整点,例如1300、1400、1100、0100 等。这遵循了 dandavis 的建议,即每隔一小时清除一次服务器,以防止垃圾在文件夹中堆积并混淆系统。

    当然,另一种方法是将检查/删除过程所需的数据附加到会话变量,然后将会话数据附加到动态创建的文件夹(会话到期时删除)。这样每个用户都有自己的个人清单,您可以省略代码中的计时删除。这样做的缺点是它可能要复杂得多,特别是如果这些文件只需要在给定的时间间隔内上传一次。

    如果您希望我解释基于会话的解决方案,请在 cmets 中询问,我会花一些时间来写;我现在不会这样做,因为它显然比这个解决方案要长得多,而且我不完全确定它是你要找的。如果我已经写的足够了,感谢您的阅读,祝您的项目好运! :)

    【讨论】:

      猜你喜欢
      • 2014-03-18
      • 2017-12-09
      • 2019-12-19
      • 2011-11-29
      • 2011-07-02
      • 2014-04-04
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      相关资源
      最近更新 更多