Câu hỏi Tôi làm cách nào để tải lên tệp không đồng bộ?


Tôi muốn tải lên một tệp không đồng bộ với jQuery. Đây là HTML của tôi:

<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

Và đây Jquery mã:

$(document).ready(function () {
    $("#uploadbutton").click(function () {
        var filename = $("#file").val();

        $.ajax({
            type: "POST",
            url: "addFile.do",
            enctype: 'multipart/form-data',
            data: {
                file: filename
            },
            success: function () {
                alert("Data Uploaded: ");
            }
        });
    });
});

Thay vì tệp đang được tải lên, tôi chỉ nhận được tên tệp. Tôi có thể làm gì để khắc phục sự cố này?

Giải pháp tạm thời

Tôi đang sử dụng Plugin biểu mẫu jQuery để tải tệp lên.


2609
2017-10-03 10:22


gốc


bạn chỉ nhận được tên tệp vì tên tệp var của bạn nhận được giá trị là $ ('# tệp'), chứ không phải tệp nằm trong đầu vào - Jimmy
Đây là một điều tốt: http://blueimp.github.io/jQuery-File-Upload/ - Tải lên ajax HTML5 - Dự phòng tuyệt đối với khung nội tuyến cho các trình duyệt không được hỗ trợ - Tải lên nhiều tệp async Chúng tôi đã sử dụng nó và nó hoạt động tuyệt vời. (Tài liệu ở đây) - Ashish Panery
jQuery Form Plugin có vẻ là cách tương thích đơn giản nhất và dễ sử dụng nhất ... tôi có đúng không? - Lyth
Kiểm tra này cũng: stackoverflow.com/questions/6974684/…, ở đây nó giải thích làm thế nào để đạt được nó thông qua jQuery - Chococroc
@Jimmy Làm thế nào anh ta sẽ nhận được các tập tin nằm trong đầu vào thay vào đó? - alex


Các câu trả lời:


Với HTML5 bạn có thể tạo các tệp tải lên bằng Ajax và jQuery. Không chỉ vậy, bạn có thể thực hiện xác thực tệp (tên, kích thước và loại MIME) hoặc xử lý sự kiện tiến trình với thẻ tiến trình HTML5 (hoặc một div). Gần đây tôi phải tạo một trình tải lên tệp nhưng tôi không muốn sử dụng Đèn flash cũng như Iframes hoặc bổ sung và sau một số nghiên cứu tôi đã đưa ra giải pháp.

HTML:

<form enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>
<progress></progress>

Trước tiên, bạn có thể làm một số xác nhận nếu bạn muốn. Ví dụ: trong sự kiện onChange của tệp:

$(':file').on('change', function() {
    var file = this.files[0];
    if (file.size > 1024) {
        alert('max upload size is 1k')
    }

    // Also see .name, .type
});

Bây giờ Ajax gửi với nút bấm của:

$(':button').on('click', function() {
    $.ajax({
        // Your server script to process the upload
        url: 'upload.php',
        type: 'POST',

        // Form data
        data: new FormData($('form')[0]),

        // Tell jQuery not to process data or worry about content-type
        // You *must* include these options!
        cache: false,
        contentType: false,
        processData: false,

        // Custom XMLHttpRequest
        xhr: function() {
            var myXhr = $.ajaxSettings.xhr();
            if (myXhr.upload) {
                // For handling the progress of the upload
                myXhr.upload.addEventListener('progress', function(e) {
                    if (e.lengthComputable) {
                        $('progress').attr({
                            value: e.loaded,
                            max: e.total,
                        });
                    }
                } , false);
            }
            return myXhr;
        }
    });
});

Như bạn có thể thấy, với việc tải lên tệp HTML5 (và một số nghiên cứu) không chỉ trở thành có thể nhưng siêu dễ dàng. Dùng thử Google Chrome vì một số thành phần HTML5 của các ví dụ không có sẵn trong mọi trình duyệt.


2336
2018-01-06 13:34



Sau đó tôi có thể sử dụng $ _FILES trong tệp upload.php không? - Alessandro Cosentino
Điều này sẽ hoạt động trong Internet Explorer nhưng chỉ có phiên bản 10. (caniuse.com/xhr2) - Samir
Không hoạt động trong IE7-9 - KevinDeus
Hi, tôi đánh giá cao PHP là ngôn ngữ của bạn lựa chọn ... nhưng tôi tự hỏi nếu bạn biết nếu điều này cũng làm việc trong ASP.NET MVC? Tôi là một nhà phát triển .NET và tôi đã cố gắng sử dụng ví dụ đơn giản của bạn để tải lên một số tệp AJAX nhưng phía máy chủ tôi không nhận được tệp tôi đã đăng qua AJAX. Tôi đang sử dụng Chrome mới nhất. - Shumii
nó là FormData những người làm tất cả các phép thuật ở đây. Hãy chắc chắn kiểm tra các tài liệu này - nó bao gồm tất cả câu hỏi của bạn về nhiều tệp và trường. - incarnate


Có nhiều plugin được tạo sẵn khác nhau để thực hiện tải lên tệp cho jQuery.

Thực hiện loại hack tải lên này không phải là trải nghiệm thú vị, vì vậy mọi người thích sử dụng các giải pháp được tạo sẵn.

Dưới đây là ít:

Bạn có thể tìm kiếm các dự án khác trên NPM (sử dụng "jquery-plugin" làm từ khóa) hoặc trên Github.


335
2017-10-15 10:35



Liên kết AjaxFUP dường như bị hỏng. Tôi nghi ngờ đây là những gì được đề cập đến: valums.com/ajax-upload - UlfR
Để có một plugin được đọc khác, luôn có Filepicker.io, đó là loại tốt đẹp ở chỗ nó đề với tất cả các vấn đề hỗ trợ tập tin lớn khó chịu, vv - brettcvz
Nó thực sự chỉ có khoảng 10 dòng vanilla JS. Nó thực sự không quá tệ. - mpen
Plugin giải pháp được tạo sẵn có thể hoạt động tốt nhưng nó không giúp sau một thời gian bạn tìm ra nó không hoạt động mà bạn nghĩ nó sẽ và bạn phải hack nó bằng các tập lệnh lạ. Vì vậy, nó đi cả hai cách. - fletchsod
Tôi có thể dùng JQuery File Uploader cho nhiều video ..? nó sẽ hỗ trợ ..? - Mr world wide


Bản cập nhật năm 2017: Nó vẫn phụ thuộc vào trình duyệt của bạn sử dụng nhân khẩu học.

Một điều quan trọng cần hiểu với HTML5 "mới" file API là không được hỗ trợ cho đến IE 10. Nếu thị trường cụ thể mà bạn nhắm đến có tỷ lệ cao hơn mức trung bình cao hơn đối với các phiên bản Windows cũ hơn, bạn có thể không có quyền truy cập vào nó.

Đi vào năm 2017, khoảng 5% trình duyệt là một trong số IE 6, 7, 8 hoặc 9. Nếu bạn đầu tư vào một tập đoàn lớn (ví dụ: đây là công cụ B2B hoặc thứ bạn đang cung cấp để đào tạo), số đó có thể là tên lửa. Chỉ vài tháng trước —trong năm 2016— tôi đã xử lý một công ty sử dụng IE8 trên hơn 60% máy của họ.

Vì vậy, trước khi bạn làm bất cứ điều gì: kiểm tra trình duyệt nào của bạn người dùng sử dụng. Nếu không, bạn sẽ học được một bài học nhanh và đau đớn về lý do tại sao "làm việc cho tôi" không đủ tốt trong việc giao hàng cho khách hàng.

Câu trả lời của tôi từ năm 2008 sau.


Tuy nhiên, có các phương thức không JS có khả năng tải lên tệp. Bạn có thể tạo iframe trên trang (bạn ẩn với CSS) và sau đó nhắm mục tiêu biểu mẫu của bạn để đăng lên iframe đó. Trang chính không cần phải di chuyển.

Đó là bài đăng "thực" nên không hoàn toàn tương tác. Nếu bạn cần tình trạng bạn cần một cái gì đó phía máy chủ để xử lý đó. Điều này thay đổi tùy thuộc vào máy chủ của bạn. ASP.NET có cơ chế đẹp hơn. Đồng bằng PHP không thành công, nhưng bạn có thể sử dụng Perl hoặc sửa đổi Apache để có được xung quanh nó.

Nếu bạn cần nhiều tệp tải lên, tốt nhất bạn nên thực hiện từng tệp một (để khắc phục giới hạn tải lên tệp tối đa). Đăng biểu mẫu đầu tiên lên iframe, theo dõi tiến trình của nó bằng cách sử dụng ở trên và khi nó kết thúc, hãy đăng biểu mẫu thứ hai lên khung nội tuyến, v.v.

Hoặc sử dụng giải pháp Java / Flash. Chúng linh hoạt hơn nhiều trong những gì họ có thể làm với các bài đăng của họ ...


237
2017-10-03 10:41



Đối với hồ sơ, bây giờ có thể thực hiện tải lên tệp AJAX tinh khiết nếu trình duyệt hỗ trợ API tệp - developer.mozilla.org/en/using_files_from_web_applications - meleyal
Trừ khi bạn cần hỗ trợ IE9. caniuse.com/fileapi - Oli
giải pháp khung nội tuyến khá đơn giản và dễ làm việc - Matthew Lock
đây là một câu trả lời khá cũ, nhưng nó là một chút sai lầm .. IE hỗ trợ XHR nguyên bản như xa trở lại như IE7, và hỗ trợ nó thông qua ActiveX như xa trở lại như IE5. w3schools.com/ajax/ajax_xmlhttprequest_create.asp. Cách thực tế để làm điều này chắc chắn là nhắm vào các thành phần flash (shockwave), hoặc tung ra một điều khiển Flash / ActiveX (Silverlight). Nếu bạn có thể tạo ra một yêu cầu và xử lý đáp ứng thông qua javascript, đó là ajax .. mặc dù, đã nói rằng, ajax đồng nghĩa với xhr, nhưng nó không tự mô tả cơ chế / thành phần gạch dưới cung cấp / trao đổi tải trọng. - Brett Caswell
@BrettCaswell Tôi đã không nói rằng AJAX / XHR là không thể, chỉ là nó đã không thể gửi một tập tin lên với họ trên phiên bản cũ - nhưng everliving - của IE. Đó là và vẫn hoàn toàn đúng. - Oli


Tôi khuyên bạn nên sử dụng Trình tải lên tốt plugin cho mục đích này. Của bạn JavaScript mã sẽ là:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});

105
2017-11-21 16:38



Nó sử dụng JSON - vì vậy đối với phiên bản PHP cũ, nó sẽ không thể sử dụng được. - Lorenzo Manucci
Dường như sạch hơn Ajax File Upload, nơi tôi cần bao gồm một đoạn mã lớn chỉ để sử dụng thứ chết tiệt. - ripper234
URL hiện là valums.com/ajax-upload. - Patrick Fisher
"Plugin này được mở nguồn dưới GNU GPL 2 trở lên và GNU LGPL 2 trở lên." Vì vậy, miễn là bạn không phân phối bản sao hoặc phiên bản đã sửa đổi, bạn không phải mở dự án của mình. - Trantor Liu
Đây là trang web (fineuploader.com) Tôi tìm thấy bây giờ , nó là V4.2. - Andrew_1510


Lưu ý: Câu trả lời này đã lỗi thời, giờ đây bạn có thể tải tệp lên bằng XHR.


Bạn không thể tải tệp lên bằng XMLHttpRequest (Ajax). Bạn có thể mô phỏng hiệu ứng bằng iframe hoặc Flash. Tuyệt vời Plugin biểu mẫu jQuery đăng các tệp của bạn thông qua iframe để có hiệu lực.


87
2017-10-03 10:36



Có, bạn có thể POST lên iframe và chụp tệp ở đó. Mặc dù vậy, tôi có rất ít kinh nghiệm với điều này, vì vậy tôi không thể thực sự bình luận về nó. - Mattias
Nhận xét nhỏ: trong các phiên bản mới nhất của chrome và firefox, có thể, stackoverflow.com/questions/4856917/… - Alleo


Điều này AJAX tải lên tệp jQuery plugin tải lên tệp somehwere và chuyển trả lời một cuộc gọi lại, không có gì khác.

  • Nó không phụ thuộc vào HTML cụ thể, chỉ cần cung cấp cho nó một <input type="file">
  • Nó không yêu cầu máy chủ của bạn phản hồi theo bất kỳ cách cụ thể nào
  • Không quan trọng bạn sử dụng bao nhiêu tệp hoặc vị trí của chúng trên trang

- Sử dụng ít nhất là -

$('#one-specific-file').ajaxfileupload({
  'action': '/upload.php'
});

- hoặc nhiều như -

$('input[type="file"]').ajaxfileupload({
  'action': '/upload.php',
  'params': {
    'extra': 'info'
  },
  'onComplete': function(response) {
    console.log('custom handler for file:');
    alert(JSON.stringify(response));
  },
  'onStart': function() {
    if(weWantedTo) return false; // cancels upload
  },
  'onCancel': function() {
    console.log('no file selected');
  }
});

81
2017-07-29 00:34



Không hoạt động với 1.9.1: | - user840250
@ user840250 jQuery 1.9.1? - Jordan Feldstein


Bao bọc cho độc giả trong tương lai.

Tải lên tệp không đồng bộ

Với HTML5

Bạn có thể tải lên tệp với jQuery sử dụng $.ajax() phương pháp nếu FormData và API tệp được hỗ trợ (cả hai tính năng HTML5).

Bạn cũng có thể gửi tệp không có FormData nhưng cả hai cách API tệp phải có mặt để xử lý tệp theo cách mà chúng có thể được gửi cùng với XMLHttpRequest (Ajax).

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
  processData: false,
  contentType: false                    // Using FormData, no need to process data.
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

Để có JavaScript nhanh, tinh khiết (không có jQuery) xem ví dụ "Gửi tệp bằng đối tượng FormData".

Dự phòng

Khi HTML5 không được hỗ trợ (không API tệp) giải pháp JavaScript thuần túy duy nhất khác (không Đèn flash hoặc bất kỳ plugin trình duyệt nào khác) là iframe ẩn kỹ thuật, cho phép mô phỏng yêu cầu không đồng bộ mà không cần sử dụng XMLHttpRequest vật.

Nó bao gồm thiết lập một khung nội tuyến làm đích của biểu mẫu với các đầu vào của tệp. Khi người dùng gửi yêu cầu được thực hiện và các tệp được tải lên nhưng phản hồi được hiển thị bên trong khung nội tuyến thay vì hiển thị lại trang chính. Ẩn iframe làm cho toàn bộ quá trình trong suốt với người dùng và mô phỏng một yêu cầu không đồng bộ.

Nếu được thực hiện đúng cách, nó sẽ hoạt động hầu như trên bất kỳ trình duyệt nào, nhưng nó có một số cảnh báo về cách lấy phản hồi từ khung nội tuyến.

Trong trường hợp này, bạn có thể thích sử dụng một trình bao bọc như Bifröst trong đó sử dụng kỹ thuật iframe nhưng cũng cung cấp jQuery Ajax transport cho phép gửi tệp chỉ với $.ajax() phương pháp như thế này:

$.ajax({
  url: 'file/destination.html', 
  type: 'POST',
  // Set the transport to use (iframe means to use Bifröst)
  // and the expected data type (json in this case).
  dataType: 'iframe json',                                
  fileInputs: $('input[type="file"]'),  // The file inputs containing the files to send.
  data: { msg: 'Some extra data you might need.'}
}).done(function(){
  console.log("Success: Files sent!");
}).fail(function(){
  console.log("An error occurred, the files couldn't be sent!");
});

bổ sung

Bifröst chỉ là một trình bao bọc nhỏ bổ sung thêm hỗ trợ dự phòng cho phương thức ajax của jQuery, nhưng nhiều plugin được nhắc đến như Plugin biểu mẫu jQueryhoặc là Tải lên tệp jQuery bao gồm toàn bộ ngăn xếp từ HTML5 đến các dự phòng khác nhau và một số tính năng hữu ích để giảm bớt quá trình này. Tùy thuộc vào nhu cầu và yêu cầu của bạn, bạn có thể muốn xem xét việc triển khai không đúng hoặc một trong các plugin này.


75
2017-08-25 14:17



Một điều cần lưu ý, dựa trên tài liệu: bạn cũng nên gửi contentType: false. Khi tôi không gửi thông báo này với chrome, loại nội dung biểu mẫu đã bị vô hiệu hóa bởi jQuery. - ash
Câu trả lời hay. Một số gợi ý để cải thiện: Xóa các phần của mã không liên quan đến câu trả lời, ví dụ: .done() và .fail() callbacks. Ngoài ra, một ví dụ mà không sử dụng FormData và một danh sách các pro / cons sẽ là tuyệt vời. - Zero3
Tôi gặp lỗi này: TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement. - candlejack


Tôi đã sử dụng kịch bản bên dưới để tải lên hình ảnh có thể hoạt động tốt.

HTML

<input id="file" type="file" name="file"/>
<div id="response"></div>

JavaScript

jQuery('document').ready(function(){
    var input = document.getElementById("file");
    var formdata = false;
    if (window.FormData) {
        formdata = new FormData();
    }
    input.addEventListener("change", function (evt) {
        var i = 0, len = this.files.length, img, reader, file;

        for ( ; i < len; i++ ) {
            file = this.files[i];

            if (!!file.type.match(/image.*/)) {
                if ( window.FileReader ) {
                    reader = new FileReader();
                    reader.onloadend = function (e) {
                        //showUploadedItem(e.target.result, file.fileName);
                    };
                    reader.readAsDataURL(file);
                }

                if (formdata) {
                    formdata.append("image", file);
                    formdata.append("extra",'extra-data');
                }

                if (formdata) {
                    jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');

                    jQuery.ajax({
                        url: "upload.php",
                        type: "POST",
                        data: formdata,
                        processData: false,
                        contentType: false,
                        success: function (res) {
                         jQuery('div#response').html("Successfully uploaded");
                        }
                    });
                }
            }
            else
            {
                alert('Not a vaild image!');
            }
        }

    }, false);
});

Giải trình

Tôi sử dụng câu trả lời div để hiển thị hoạt ảnh tải lên và phản hồi sau khi tải lên xong.

Phần tốt nhất là bạn có thể gửi thêm dữ liệu như id và vv với tệp khi bạn sử dụng tập lệnh này. Tôi đã đề cập đến nó extra-data như trong kịch bản.

Ở cấp độ PHP, thao tác này sẽ hoạt động như tải lên tệp thông thường. có thể truy xuất thêm dữ liệu dưới dạng $_POST dữ liệu.

Ở đây bạn không sử dụng plugin và nội dung. Bạn có thể thay đổi mã như bạn muốn. Bạn không mù quáng mã hóa ở đây. Đây là chức năng cốt lõi của bất kỳ tải lên tệp jQuery nào. Trên thực tế Javascript.


57
2018-01-25 11:03



-1 để sử dụng jQuery và không sử dụng công cụ chọn và bộ điều khiển sự kiện. addEventListener không phải là trình duyệt chéo. - Mark
Bởi vì sẽ là vô nghĩa khi thêm một câu trả lời riêng biệt, chủ yếu dựa trên câu trả lời này, chỉ với một vài thay đổi. Thay vào đó, câu trả lời này cần được sửa chữa. - Mark
@RainFromHeaven, xin vui lòng, bạn có thể chỉnh sửa câu trả lời? Tôi không biết làm thế nào để làm điều đó theo cách của trình duyệt chéo. - Thiago Negri
Vẫn không hoạt động trong IE 9 trở xuống. Tất cả người dùng vẫn sử dụng các phiên bản đó của IE. - Pierre
Ai đó có thể vui lòng giải thích làm thế nào điều này có thể được thực hiện để làm việc trong asp.net? Tôi có sử dụng webmethod không? Nếu có thì nó sẽ trông như thế nào? - Arbaaz


Tôi đã đi qua một vài thư viện tải lên tệp dựa trên jQuery thực sự mạnh mẽ. Kiểm tra chúng:

  1. Plupload
  2. Tải lên tệp jQuery
  3. Trình tải lên

55
2018-04-08 16:43