简体   繁体   English

JQuery表单插件文件上传使用POST重定向到POST响应

[英]JQuery Form Plugin File Upload using POST redirects to POST response

Please help guys, This one is a major BLOCKER! 请帮帮忙,这个是一个主要的BLOCKER!

I have a project that uses NodeJS + jQuery Form Plugin + Typescript in which I am trying to do a file upload. 我有一个使用NodeJS + jQuery Form Plugin + Typescript的项目,我正在尝试上传文件。 After the file upload the server sends a response to the POST message which renders on the screen. 文件上传后,服务器会向POST消息发送响应,该消息在屏幕上呈现。 The file does get uploaded successfully and completely before the POST response renders on the screen. 在POST响应呈现在屏幕上之前,文件确实已成功上传。 I expect the POST response to call the "success" function instead of having the page redirected to show the JSON response. 我希望POST响应调用“成功”函数,而不是重定向页面以显示JSON响应。

Here's the code: 这是代码:

$(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);
        }
    });
});

the success function does not get called (which means the alert message doesn't show). 不会调用success函数(这意味着警报消息不会显示)。 The JSON data just gets rendered on the screen like this: JSON数据只是在屏幕上呈现如下:

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

There is an error on the console that says: 控制台上有一个错误:

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

Here's the server side code that handles it. 这是处理它的服务器端代码。 The server uses NodeJS formidable module. 服务器使用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;
    }

--Update-- --Update--

If I do $.ajax instead of this.ajax . 如果我做$.ajax而不是this.ajax The file does not upload. 该文件无法上传。 The browser console shows an error: 浏览器控制台显示错误:

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. 

Based on your comment: 根据您的评论:

"Thanks for that suggestion. $.ajax does not load the at all. It shows an error which you may know of. Although your suspicion is right because, when I use "this.ajax" the file does get uploaded but the console shows an error "Type has no method ajax" “感谢你的建议。$ .ajax根本没有加载。它显示了你可能知道的错误。虽然你的怀疑是对的,因为当我使用”this.ajax“文件确实上传但控制台显示错误“类型没有方法ajax”

  • You can't upload files using $.ajax() the same way you usually upload your form data. 使用$.ajax()上传文件的方式与上传表单数据的方式相同。
  • Because of the error when you use this.ajax the form gets submitted. 由于使用this.ajax时出现错误,表单将被提交。 That's why you see the JSON response in the browser. 这就是您在浏览器中看到JSON响应的原因。

The question is where does this.ajax come from? 问题是this.ajax来自哪里? Did you copy the code from an example that uses a library you haven't included? 您是否从使用未包含的库的示例中复制代码?

In order to upload files via AJAX you need some kind of plugin (doing it yourself is some effort, especially if you need support for older browsers). 要通过AJAX上传文件,您需要某种插件(自己动手做一些努力,特别是如果您需要支持旧浏览器)。

Update 更新

The submit handler should be as follows: 提交处理程序应如下所示:

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);
  });
});

Explanation: Since you want to call a jQuery plugin you need a jQuery object, hence $(this) . 说明:既然你想调用一个jQuery插件,你需要一个jQuery对象,因此$(this) ajaxSubmit() does not need any arguments (you can pass in options if you want, though). ajaxSubmit()不需要任何参数(如果你愿意,你可以传入选项)。 Because I didn't pass in arguments the callbacks are appended, in this case with done and fail (instead of success and error ). 因为我没有传入参数,所以附加了回调,在这种情况下是donefail (而不是successerror )。

Replace this.ajax("http://..." to url:form.attr('method') 将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){
      }});

Are you asking why am I getting the error: 你问我为什么会收到错误:

XMLHttpRequest cannot load localhost/. XMLHttpRequest无法加载localhost /。 No 'Access-Control-Allow-Origin' header is present on the requested resource. 请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'localhost:8080' is therefore not allowed access. 因此不允许原点'localhost:8080'访问。

If so then what you need on your localhost server (assuming that is also Node) is a header set on the response from localhost to allow the Origin of localhost:8080 to access this resource like this: 如果是这样,那么你在localhost服务器上需要的东西(假设也是Node)是来自localhost的响应的头集,允许localhost:8080访问这个资源,如下所示:

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

Or perhaps you are actually trying to request from the same server but forgot that 8080 is your test server: if so then in your test you should list your URL as 或者您实际上是尝试从同一台服务器请求但忘记8080是您的测试服务器:如果是,那么在您的测试中,您应该将您的URL列为

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

or to repeat the current origin: 或重复当前来源:

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

Your last alternative to avoiding this (if you can't set the Origin policies on the response) is to use a jsonp service which is less strict but also less featured, but that's not appropriate for your task so I won't go into that. 你避免这种情况的最后一种方法(如果你不能在响应上设置Origin策略)是使用一个jsonp服务,这个服务不那么严格但功能也较少,但是这不适合你的任务所以我不会进入那个。

Either way once you get past the Origin policy you'll have other hurdles as @zeroflagL mentions. 无论哪种方式,一旦你超越原始政策,你将有其他障碍,如@zeroflagL提到。 Here's a method that might suit you: How to handle cross domain iframe file upload json response? 这是一个可能适合您的方法: 如何处理跨域iframe文件上传json响应?

I think there are several different issues with your client-side code. 我认为您的客户端代码存在几个不同的问题。

I see that you define $form but I never see where you define form . 我看到你定义$form但我从来没有看到你在哪里定义form You then call form.attr(...) . 然后调用form.attr(...) Unless you have defined form somewhere else this will immediately throw an error. 除非你在其他地方定义了form ,否则会立即抛出错误。

More importantly, standard $.ajax() cannot upload files on older browsers (even as recent as IE 9!) The ability to do an XHR file upload was added in XHR2 (see CanIUse ). 更重要的是,标准的$.ajax()无法在旧版浏览器上上传文件(即使是最近的IE 9!)XHR2中添加了执行XHR文件上传的功能(参见CanIUse )。 If you intend for your web app to have compatibility with any down-level browsers you'll need to work around this limitation in some way. 如果您希望您的Web应用程序与任何低级浏览器兼容,则需要以某种方式解决此限制。

The good news is that there are a variety of plugins that do most of the work for you. 好消息是,有各种各样的插件可以为您完成大部分工作。 If you are using a version of jQuery greater than 1.6 I would recommend looking at the jQuery File Upload Plugin . 如果您使用的jQuery版本大于1.6,我建议您查看jQuery文件上传插件 It uses the new XHR file upload functionality when available and falls back on iFrame Transport in browsers that don't support the new hotness. 它在可用时使用新的XHR文件上载功能,并在不支持新热点的浏览器中使用iFrame Transport。 While the iFrame Transport is simple and clever you don't really need to know anything about it, because the plugin abstracts it away. 虽然iFrame Transport简单而聪明,但您并不需要了解它,因为插件将其抽象出来。 The plugin is completely free too. 这个插件也是完全免费的。

The Basic Plugin will do the dirty work for you and the full featured version even has a built in UI. Basic Plugin将为您完成脏工作,全功能版本甚至还有内置的UI。 There's plenty of details on how to implement the server side methods as well. 关于如何实现服务器端方法的详细信息很多。 The basic syntax is super simple: 基本语法非常简单:

$("#fileUploadForm").fileupload()

If you're looking for something even lighter weight, the iFrame Transport Plugin may be all you need. 如果您正在寻找更轻巧的东西, iFrame Transport Plugin可能就是您所需要的。 (It's free as well.) I just implemented it in a project today. (它也是免费的。)我今天刚刚在一个项目中实现了它。 It's a single very well documented JS file. 这是一个记录良好的JS文件。 It enhances the standard functionality of the $.ajax() function. 它增强了$.ajax()函数的标准功能。 The key is specifying iframe: true in your list of AJAX options. 关键是在AJAX选项列表中指定iframe: true Your ajax call would probably look something like this: 你的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);
    }
});

On a side note, if you want to make extra sure the non-AJAX POST doesn't occur, you can add another line to your code: 另外,如果您想进一步确保不会发生非AJAX POST,您可以在代码中添加另一行:

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

preventDefault() will cancel the POST, even if an error occurs in the code that follows. preventDefault()将取消POST,即使preventDefault()的代码中发生错误也是如此。

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){
      }});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM