【问题标题】:Creating a smart remote upload script with jQuery AJAX and PHP使用 jQuery AJAX 和 PHP 创建智能远程上传脚本
【发布时间】:2013-12-25 13:42:21
【问题描述】:

我目前正在创建一个图像托管脚本,到目前为止一切顺利。我已经使用了几个插件来创建本地上传过程,使用拖放 + AJAX 完全可以正常工作。现在我已经转移到需要使用 jQuery AJAX 和 PHP 脚本创建远程上传过程来处理整个事情的部分。

它是如何工作的

我的想法是这样的:页面中间有一个大框,接受要远程上传的 URL。一旦 有效 URL(s) 被传递到文本区域,它们将立即通过 jQuery AJAX 发送到服务器端脚本。它与 keyup 事件绑定。

看起来是这样的: http://i.imgur.com/NhkLKii.png
“HERE COME THE URLS” 部分已经是一个文本区域 - 所以该部分已经完成。


我需要帮助的地方

整个情况的问题是:一旦有有效的 URL 粘贴到文本区域,必须立即将它们转换为某种类型的框,其中还包括上传进度。看起来像这样的东西(从本地上传部分复制):http://i.imgur.com/q7RyDmb.png

本地上传的进度指示器很容易实现,因为这是我使用的插件提供的功能,但是我不知道如何指示远程上传的进度 ,完全是从零开始制作的。

这就是我想象的逻辑流程:

  1. 用户将一些 URL 粘贴到文本区域中
  2. 有一个客户端检查来验证粘贴的 URLs
  3. 经过验证的 URL 被发送到 upload.phpkeyup(?)
  4. 网址正在处理中
  5. 在上传过程中,我们会在 knob (?) 中向用户显示进度
  6. PHP 脚本完成该过程并返回上传的 URL
  7. 我在 AJAX success 回调中更新页面以显示上传的文件

所以,我不清楚标有 (?) 的两个流程 - 我不知道如何实现这些...


我尝试过的

嗯,我不只是来这里要求你为我做一切,但我遇到了一个死胡同,我不知道如何继续。到目前为止,我所做的是从文本区域收集 URL,如果有多个 URL 由换行符 (\n) 分隔,我只需使用 split 获取粘贴文本数组,然后使用另一个循环内的函数来验证它们是否是 URL。如果在文本区域值内没有检测到换行符,那么我只需检查提供的一行。在每种情况下,我都将整个文本区域发送到 PHP 脚本,因为 我不知道如何在 jQuery 中删除无效 URL。我在 PHP 中创建了一个名为 debug() 的函数,它将任何内容存储到 debug.log 文件中,当我将某些内容粘贴到文本区域时,这就是我得到的(一次尝试):

https://www.google.com/https://www.google.com/

我在文本区域粘贴了一次https://www.google.com/,但它在 PHP 端被记录了两次,我无法确定原因。

这就是我的 jQuery 的样子:

// Remote upload
    var char_start  = 10;
    var index       = 0;
    var urls        = $('.remote-area');
    var val_ary     = [];

    urls.keyup(function(){      
        if (urls.val().length >= char_start)
        {           
            var has_lbrs = /\r|\n/i.test(urls.val());
            val_ary = urls.val().split('\n');

            if (has_lbrs)
            {
                for (var i = 0; i < val_ary.length; i++)
                {
                    if (!validate_url(val_ary[i]))
                    {
                        val_ary.splice(i, 1);
                        continue;   
                    }       
                }

                $.ajax({
                    type: 'POST',
                    url: 'upload.php',
                    data: {
                        upload_type: 'remote', // Used to determine the upload type in PHP
                        urls: val_ary, // Sending the whole array here
                    },
                });
            }
            else
            {
                if (!validate_url(urls.val()))
                {
                    // Display an error here
                    return; 
                }

                $.ajax({
                    type: 'POST',
                    url: 'upload.php',
                    data: {
                        upload_type: 'remote', // Used to determine the upload type in PHP
                        urls: urls.val(), // Sending what's in the text area
                    },
                });
            }
        }
    });

问题

所以最后的问题是:

  • 如何将我的信息正确地发送到 PHP 脚本,只有有效的 URL 并在我的 PHP 脚本中让它们“可处理”
  • 如何指示上传进度?

如果我在提问时有什么不清楚的地方,请告诉我,我会尝试重新解释。

谢谢。


更新

2013 年 9 月 12 日

我想我已经设法解决了双重发送问题,即我的 AJAX 会将相同的信息两次发送到 PHP 脚本。我所做的是延迟匿名函数中的代码,该函数将文本区域内容发送到 PHP 脚本用户停止输入 2 秒后。一旦用户再次停止输入,计时器就会重置并且会发出新的 AJAX 请求。所以,我假设这个问题已经解决了。如果有什么奇怪的事情我会回来的。

现在我还剩下进度指示器部分。非常感谢您对此的看法。

我的新代码: http://pastebin.com/SaFSLeE9

【问题讨论】:

  • 唯一能正确格式化 Stack Overflow 问题的人。让我在这里都泪流满面
  • URL 是否可能因为发送了两次而被记录了两次?绑定到keyup 可能会在输入网址时发送网址。要检查 url 的有效性,您可以通过 jQuery 发出 HEAD 请求以检查它是否有效(HEAD 仅返回标头,而不是文件)。缓存您已经检查/发送的所有网址可能是个好主意。

标签: javascript php jquery html ajax


【解决方案1】:

就来回交流进度而言,您正在寻找的是“推动”。那是指服务器向客户端发送数据的技术,而不是相反,这是标准的 HTTP 做事方式。

您有很多可用的选项,如解释性Wikipedia article 中所述,但可能与此主题更相关的是Comet。发生的情况是你触发和$.ajax 调用就像你现在拥有的一样,但是你设置了一个很长的超时。这实质上为服务器提供了一个“通道”,可以在数据可用时将数据发送回页面。

因此,您需要的是服务器上的.php,它能够处理长轮询,并将随着上传进度的变化将数据发送回页面(可能以数组形式用于多次上传)。 This article 应该让您开始使用一些 jQuery 代码。请记住,此请求不会转到upload.php。这个请求转到一个不同的脚本,它只处理上传百分比并且只在数据可用时返回数据,它不会像所有其他脚本一样立即返回 - Ajax 会很高兴地等待数据。

另外,不要将您的代码与has_lbrs 分开。一行或多行不是不同的情况,一行只是多行的边缘情况。您正在不必要地复制代码。 else 案例在一般情况下会破坏什么?此外,else 案例中的“错误处理”具有误导性。您所做的唯一错误报告是只有一行并且它是错误的。如果你有两条线并且它们都错了怎么办?您的代码会很高兴地向upload.php 发送一个空数组。

这就是为什么我认为你不应该那样分离你的代码,因为那样你会分离逻辑,甚至不会注意到它。

【讨论】:

  • 感谢您的回答。我想问一些问题......假设我已经在我的 jQuery 中创建了那个轮询系统,但是我应该向处理百分比的 PHP 脚本发送什么?我应该从脚本向 AJAX 调用发回什么?这些都是让我困惑的问题。我还想提一下,我的 Javascript 与问题有所不同;有机会我会更新的。
  • 每次您想要更新进度条时,您都会发回您想要更新进度条的百分比。你不需要向它发送任何东西,ajax 只是对数据的请求。如果您问“我如何获得计算百分比的脚本”,那取决于您没有提供的后端上传脚本。您只需要上传脚本的某种方式来更新 的进度,然后让更新脚本读取 并将其发送回轮询 ajax 请求。
  • 那么,如果我提供了一个服务器端脚本,你能给我一些示例代码的视觉效果吗?只是一个简短的例子,让我开始。我将尝试简要描述 PHP 脚本的作用:它使用 file_get_content 获取 URL,使用我将提供的函数检查文件的扩展名,然后使用 file_put_contents 将文件存储在服务器中。这实际上是一个非常简单的脚本。
  • 这会让你的服务器在大文件上崩溃。如果您想正确执行此操作,则必须使用从源文件到目标文件的二进制流,而不是先将整个内容读入内存。试试teddy.fr/2007/11/28/how-serve-big-files-through-php 之类的东西 - 这应该会让您在写入文件块之间更新 变得微不足道。然后另一个脚本可以简单地读取您正在更新的 并将进度报告回页面。
【解决方案2】:

在我看来,最好的方法是使用 ajax 调用您的 cURL 脚本并使用它来将您的文件上传到远程服务器上。您的应用服务器上需要 ajax.js、curl.php、index.php(您想要的任何名称)。以及远程服务器上的 image.php、class.image.php(你想要的任何名称)。

我为我的应用执行的步骤

1) 我要从我的 index.php 文件上传一张图片。它将使用 ajax.js 调用 curl.php 文件,并且 cURL 文件将检查文件的扩展名和所有内容(为了您的应用程序的安全,请确保您希望允许用户上传什么内容)。

2) 现在 curl 文件将使用默认文件名将文件上传到您预先定义的临时文件夹。

3) 现在,如果 move_uploaded_file 函数(我在脚本中使用)成功运行,您可以调用 cURL 函数将您的数据作为帖子发送到远程服务器上,图像文件将接收帖子并进一步处理。您可以将您的类保存在 image.php 中,也可以根据需要在远程服务器上创建两个 PHP 文件。

4) 现在,在您的类文件中,您应该再次检查文件是否为图像文件(以及您想要允许的任何文件)以提高安全性。如果文件是好的,处理重命名它,如果你想把文件添加到文件夹中。

5) 使用远程数据库连接将文件的新名称和文件夹名称添加到您的数据库中。因此,cURL 将在同一页面上显示结果。

现在,为什么是 cURL?我更喜欢 cURL,因为您可以在 if else 条件下为您的通信添加密钥或 API 以使其更安全。您将接收所有帖子的远程服务器文件将检查 API == 'yourKey' 是否会进行处理,否则它将无法处理,并且没有人能够使用机器人和所有内容在您的服务器上发送图像。

我不知道我的回答是否会对您有所帮助,可能我的方法冗长或对您的应用程序不利,但尝试谷歌有关 cURL 的信息,您会明白我想说什么。希望你喜欢它并理解它。如果有任何疑问,您可以随时问我。

【讨论】:

  • 我对 cURL 非常熟悉,我最擅长的是 Javascript,哈哈。实际上,我已经使用 cURL 来验证上传文件的扩展名,这是安全的方法。我肯定会考虑这种实现方式。谢谢你的建议。
猜你喜欢
  • 2012-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-15
  • 2013-07-07
  • 1970-01-01
相关资源
最近更新 更多