确保将所有文件上载到Web服务器

时间:2016-01-21 22:20:03

标签: javascript file-upload server

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

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

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

2 个答案:

答案 0 :(得分:1)

由于您单独上传每个文件,因此您的服务器无法知道所有文件是否都已成功。

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

如果上传的文件出现故障(上一次上传已通知下一个不同的文件),则服务器应中止上传和回滚(根据您保存的列表删除文件)并返回错误对客户。

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

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

答案 1 :(得分:0)

实际上有一个完美的,手工制作的PHP函数 - file_exists('filename'),它返回true或false,具体取决于是否存在'filename'。如果远程存储文件,则必须包含从根到文件的路径,因此在您的情况下,它将是file_exists('files / filename')。要一次检查所有文件,只需使用另一个for循环和一些if语句(以下假设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循环来验证文件[n]是否存在。对于每个具有可验证存在的文件,计数器($ safeFiles)递增1。

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

使用unlink()函数存在一些缺陷,详见here;确保将目标数据限制为一个文件夹,以便您必须删除尽可能少的引用数。一旦数据从其框中移出,您可以指数地删除更多的引用,并且当您删除越来越多的单个文件实例时,该函数可能会变得越来越长。

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

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

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