【问题标题】:JQuery Form Plugin File Upload using POST redirects to POST response使用 POST 重定向到 POST 响应的 JQuery 表单插件文件上传
【发布时间】:2014-05-02 10:28:27
【问题描述】:

请帮助大家,这是一个主要的 BLOCKER!

我有一个使用 NodeJS + jQuery Form Plugin + Typescript 的项目,我正在尝试上传文件。文件上传后,服务器向屏幕上呈现的 POST 消息发送响应。该文件确实在 POST 响应呈现在屏幕上之前成功且完整地上传。我希望 POST 响应调用“成功”函数,而不是重定向页面以显示 JSON 响应。

代码如下:

$(new ID().setAsRoot().selectId()).append(
    "<form id=\"fileUploadForm\" accept-charset=\"utf-8\" method=\"post\" action=\"/upload\" enctype=\"multipart/form-data\">" +
        "<input id = \"filename\" type=\"file\" name=\"userfile\" multiple=\"multiple\" />" +
        "<button type=\"submit\" id = \"submitButton\"> Upload </button></form>");

var form = $("#fileUploadForm");
form.submit(function (e) {
    //e.preventDefault();
    this.ajaxSubmit({
        type: form.attr('method'),
        url: form.attr('action'),
        data: form.serialize(),
        success: function (data) {
            var x = JSON.parse(data);
            alert("Success : " + x);
        },
        error: function (data) {
            var x = JSON.parse(data);
            alert("Error : " + x);
        }
    });
});

没有调用成功函数(这意味着不显示警报消息)。 JSON 数据会像这样在屏幕上呈现:

{
  "path": "data\\cb3409f1cc234ec3f64b60d80be13a3e.html",
  "name": "feed.html"
}

控制台出现错误提示:

Uncaught SyntaxError: Unexpected token : shortcut_manager.js:123
(anonymous function) shortcut_manager.js:123
(anonymous function) extensions::messaging:327
Event.dispatchToListener extensions::event_bindings:386
Event.dispatch_ extensions::event_bindings:371
Event.dispatch extensions::event_bindings:392
dispatchOnMessage

这是处理它的服务器端代码。服务器使用NodeJS强大的模块。

public upload(req:express.Request, res) {

        var form = new formidable.IncomingForm();
        var originalFileName:String;
        var filePath:String;
        form.uploadDir = this.directory;
        form.keepExtensions = true;
        form.type = 'multipart';
        var fields = [];
        form
            .on("error", function (err) {
            })
            .on("field", function (field, value) {
            })
            .on("end", function () {
                res.send({
                    path: filePath,
                    name: originalFileName
                });
            })
            .on("file", function (name, file:formidable.File) {
                originalFileName = file.name;
                filePath = file.path;
            });
        form.parse(req);
        return;
    }

--更新--

如果我使用$.ajax 而不是this.ajax。文件不上传。浏览器控制台显示错误:

XMLHttpRequest cannot load http://localhost/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. 

【问题讨论】:

  • 您不必在响应中添加状态码吗?
  • 在 POST 响应中添加了状态代码 - 仍然无法正常工作 - 请参阅上面的更新代码。谢谢
  • 好的,抱歉,这只是一个快速的想法。另一种是:在您的submit 回调中使用$(this) 而不是this。我感觉您正在访问 HTML 元素。顺便说一句,您在开发者控制台中是否遇到任何错误?
  • 你指的是来自“this.ajaxSubmit()”的“this”。那不是回调。如果我用 $(this) 替换它,IDE 会抛出错误:“参数类型与参数不匹配”。谢谢。
  • 听起来表单提交正常。您是否在控制台中收到任何错误?我也认为是$.ajax 而不是this.ajax

标签: jquery post jquery-forms-plugin


【解决方案1】:

根据您的评论:

“谢谢你的建议。$.ajax 根本不加载。它显示了一个你可能知道的错误。虽然你的怀疑是正确的,因为当我使用“this.ajax”时,文件确实被上传了,但是控制台显示错误“Type has no method ajax”

  • 您无法像通常上传表单数据一样使用$.ajax() 上传文件。
  • 由于使用this.ajax 时的错误,表单被提交。这就是您在浏览器中看到 JSON 响应的原因。

问题是this.ajax 来自哪里?您是否从使用您未包含的库的示例中复制代码?

为了通过 AJAX 上传文件,您需要某种插件(自己动手做需要付出一些努力,特别是如果您需要支持旧版浏览器)。

更新

提交处理程序应如下所示:

form.submit(function (e) {
  e.preventDefault();
  $(this).ajaxSubmit().done(function (data) {
    var x = JSON.parse(data);
    alert("Success : " + x);
  }).fail(function (data) {
    var x = JSON.parse(data);
    alert("Error : " + x);
  });
});

解释:既然你想调用一个 jQuery 插件,你需要一个 jQuery 对象,因此是$(this)ajaxSubmit() 不需要任何参数(不过,如果需要,您可以传入选项)。因为我没有传入参数,所以附加了回调,在这种情况下是donefail(而不是successerror)。

【讨论】:

  • 感谢您的评论。我已经修改了这个问题并添加了更多细节。我正在使用 JQuery 表单插件进行上传。请再看看这个问题。感谢您的帮助。
  • @EternallyCurious 有数百个表单插件。你用哪一个?顺便说一句,这些插件中的大多数都无法处理文件上传。
  • @zeroflagL 我按照您的建议修改了代码。虽然“$(this)”会引发错误,但我只是使用“this”。回调函数 done 和 fail 不会被调用。除此之外,页面不再重定向到 JSON 响应 - 这是我发布这个问题的核心问题。所以赏金全是你的。非常感谢您的努力。
  • @zeroflagL 实际上我使用的是“form.ajaxSubmit”而不是“this.ajaxSubmit”或“$(this).ajaxSubmit”。使用“this”根本不会上传文件。
【解决方案2】:

将 this.ajax("http://..." 替换为 url:form.attr('method')

  var form = $("#fileUploadForm");     
  $.ajax({
      type:form.attr('method'),
       url:form.attr('action'),
      data:form.serialize(),
             success: function(data){
      }});

【讨论】:

  • 谢谢,这是一个非常有用的方法,我已经相应地更改了我的代码 - 但结果根本没有改变。完全相同的事情仍在发生。您是否需要从服务器端了解任何信息。我也发布了一些服务器端代码。
【解决方案3】:

你是在问我为什么会收到错误消息:

XMLHttpRequest 无法加载 localhost/。请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'localhost:8080' 不允许访问。

如果是这样,那么您需要在 localhost 服务器(假设也是 Node)上设置来自 localhost 的响应的标头,以允许 localhost:8080 的来源访问此资源,如下所示:

res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');

或者也许您实际上是在尝试从同一台服务器请求但忘记了 8080 是您的测试服务器:如果是这样,那么在您的测试中您应该将您的 URL 列为

$.ajax("http://localhost:8080", { //....

或重复当前原点:

$.ajax( window.location.origin,{ // ....

避免这种情况的最后一种选择(如果您无法在响应中设置 Origin 策略)是使用jsonp 服务,该服务不那么严格但功能也较少,但这不适合您的任务,所以我赢了不要进入那个。

无论哪种方式,一旦您通过了 Origin 政策,您将遇到@zeroflagL 提到的其他障碍。这是一种可能适合您的方法:How to handle cross domain iframe file upload json response?

【讨论】:

  • 感谢您的评论。我已经修改了这个问题。我正在使用 JQuery 表单插件进行上传。请再看看。感谢您的帮助。
  • @EternallyCurious,如果您仍然遇到访问控制错误,那么无论您打算如何上传文件,您仍然需要查看我上面的答案。
【解决方案4】:

我认为您的客户端代码存在几个不同的问题。

我看到你定义了$form,但我从来没有看到你在哪里定义form。然后您拨打form.attr(...)。除非您在其他地方定义了form,否则这将立即引发错误。

更重要的是,标准$.ajax() 无法在旧浏览器上上传文件(即使是最新的 IE 9!)XHR2 中添加了上传 XHR 文件的功能(请参阅CanIUse)。如果您打算让您的 Web 应用程序与任何低级浏览器兼容,则需要以某种方式解决此限制。

好消息是有多种插件可以为您完成大部分工作。如果您使用的 jQuery 版本大于 1.6,我建议您查看 jQuery File Upload Plugin。它在可用时使用新的 XHR 文件上传功能,并在不支持新热点的浏览器中使用 iFrame Transport。虽然 iFrame Transport 简单而聪明,但您实际上并不需要了解任何有关它的信息,因为插件将其抽象出来。该插件也是完全免费的。

Basic Plugin 将为您完成繁琐的工作,全功能版本甚至具有内置 UI。还有很多关于如何实现服务器端方法的细节。基本语法超级简单:

$("#fileUploadForm").fileupload()

如果您正在寻找更轻的东西,iFrame Transport Plugin 可能就是您所需要的。 (它也是免费的。)我今天刚刚在一个项目中实现了它。这是一个文档非常完整的 JS 文件。它增强了$.ajax() 函数的标准功能。关键是在 AJAX 选项列表中指定 iframe: true。您的 ajax 调用可能看起来像这样:

$.ajax("http://localhost", {
    type: $form.attr('method'),
    url: $form.attr('action'),
    data: $form.serialize(),
    dataType: "JSON",
    iframe: true,
    files: $("#MyFileInputId"),
    success: function (data) {
        alert("Success : " + data);
    },
    error: function (data) {
        alert("Error : " + data);
    }
});

附带说明,如果您希望额外确保不发生非 AJAX POST,您可以在代码中添加另一行:

$form.submit(function (e) {
    e.preventDefault();
    // do stuff
    return false;
}

preventDefault() 将取消 POST,即使后面的代码出现错误。

【讨论】:

  • 感谢您的评论。我已经修改了这个问题,因为解决了一小部分问题 - 并添加了更多细节。我正在使用 JQuery 表单插件进行上传。请再看看这个问题。我感谢您的帮助。 PS。 preventDefault() 完全阻止上传。
  • 这是preventDefault() 的预期结果。如果没有该行,浏览器仍在上传文件,因为 AJAX 帖子引发了错误并且从未到达 return false 语句。这允许浏览器执行默认操作(标准的非 AJAX HTML 表单 POST)。
【解决方案5】:
var form = $("#fileUploadForm");     
 $.ajax({
      type:form.attr('method'),
      url:form.attr('action'),
      dataType: 'json', //  Expect a return value of json
      data:form.serialize(),
             success: function(data){
      }});

【讨论】:

    猜你喜欢
    • 2011-04-22
    • 1970-01-01
    • 2012-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多