Làm cách nào để tải lên các tệp không đồng bộ?


2914

Tôi muốn tải lên một tệp không đồng bộ với jQuery.

$(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: ");
            }
        });
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

Thay vì tập tin đượ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 vấn đề này?


Có nhiều plugin được tạo sẵn khác nhau khi thực hiện tải lên tệp cho jQuery. Thực hiện các kiểu hack tải lên này không phải là một trải nghiệm thú vị, vì vậy mọi người thích sử dụng các giải pháp làm sẵn. Dưới đây là một số: - Trình tải lên tệp JQuery - Plugin tải lên nhiều tệp - Tải lên nhiều tệp nhỏ - Tải lên tệp jQuery Bạn có thể tìm kiếm thêm các dự án trên NPM (sử dụng "jquery-plugin" làm từ khóa) hoặc trên Github.
Vui vẻ

72
bạn chỉ nhận được tên tệp vì tên tệp var của bạn đang nhận giá trị $ ('# file'), không phải là tệp nằm trong đầu vào
Jimmy

21
Đây là một cách tốt: http://blueimp.github.io/jQuery-File-Upload/ - Tải lên HTML5 ajax - Dự phòng duyên dáng cho iframes cho các trình duyệt không được hỗ trợ - Tải lên async nhiều tệp Chúng tôi đã sử dụng và nó hoạt động rất tốt. ( Tài liệu ở đây )
Ashish Panery

3
Cũng kiểm tra cái này: stackoverflow.com/questions/6974684/ , ở đây nó giải thích cách đạt được nó thông qua jQuery
Chococroc

2
@Jimmy Làm thế nào để anh ấy có được tập tin nằm trong đầu vào thay thế?
alex

Câu trả lời:


2519

Với HTML5, bạn có thể thực hiện tải lên tệp 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 bằng thẻ tiến trình HTML5 (hoặc 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 Flash cũng như Iframes hoặc plugin 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>

Đầu tiên, bạn có thể thực hiện một số xác nhận nếu bạn muốn. Ví dụ: trong trường .on('change')hợp 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:

$(':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ở nên khả thi mà còn cực kỳ dễ dàng. Hãy dùng thử với 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.


14
Sau đó tôi có thể sử dụng $ _FILES trong upload.php không?
Alessandro Cosentino

71
Điều này sẽ hoạt động trong Internet Explorer nhưng chỉ có Phiên bản 10. ( caniuse.com/xhr2 )
Tyler

18
Xin chào, tôi đánh giá cao PHP là ngôn ngữ bạn chọn ... nhưng tôi tự hỏi liệu bạn có biết nếu nó cũng hoạt động trong ASP.NET MVC không? 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 để thực hiện một số tải lên 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

25
Đó là FormData , người thực hiện 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.
hóa thân vào

4
Chỉ để người khác không mất hàng giờ ... điều name="file"này rất quan trọng đối với <input>thẻ tệp nếu bạn sẽ sử dụng dữ liệu trong PHP (và có thể ở những nơi khác). Tôi đã tạo một biểu mẫu một cách linh hoạt bằng cách sử dụng javascript vì vậy tôi không cần thuộc tính name nhưng phát hiện ra một cách khó khăn mà bạn hoàn toàn cần nó để truy xuất phía máy chủ dữ liệu.
Sói Kivak

273

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

Một điều quan trọng cần hiểu với fileAPI HTML5 "mới" là nó không được hỗ trợ cho đến IE 10 . Nếu thị trường cụ thể mà bạn nhắm đến có xu hướng cao hơn mức trung bình đố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 thị trường đó.

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

Đó là năm 2019 kể từ lần chỉnh sửa này, gần 11 năm sau câu trả lời ban đầu của tôi. IE9 và thấp hơn trên toàn cầu quanh mốc 1% nhưng vẫn có những cụm sử dụng cao hơn.

Điểm quan trọng mang lại từ trò chơi này bất kể tính năng nào là, hãy kiểm tra xem người dùng của bạn sử dụng trình duyệt nào . Nếu bạn không, bạn sẽ học được một bài học nhanh chóng và đau đớn về lý do tại sao "làm việc cho tôi" không đủ tốt để cung cấp cho khách hàng. caniuse là một công cụ hữu ích nhưng lưu ý nơi họ lấy nhân khẩu học của họ. Họ có thể không phù hợp với bạn. Điều này không bao giờ đúng hơn môi trường doanh nghiệp.

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


Tuy nhiên, có các phương pháp tải lên tệp không khả thi của JS. Bạn có thể tạo iframe trên trang (mà bạn ẩn bằng 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.

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

Nếu bạn cần nhiều lần tải lên tệp, tốt nhất nên thực hiện từng tệp một lần (để vượt qua 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 hoàn thành, hãy đăng biểu mẫu thứ hai lên iframe, v.v.

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


142
Đối với bản ghi, giờ đây có thể thực hiện tải lên tệp AJAX thuần túy nếu trình duyệt hỗ trợ API tệp - developer.mozilla.org/en/USE_files_from_web_appluggest
meleyal

Giải pháp iframe khá đơn giản và dễ dàng để làm việc
Matthew Lock

Đây là một câu trả lời khá cũ, nhưng nó hơi sai lệch .. IE đã hỗ trợ XHR từ trước đến nay như IE7 và hỗ trợ nó thông qua ActiveX cho đến tận 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 mục tiêu các thành phần flash (sóng xung kích) hoặc triển khai đ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ý phản hồi thông qua javascript, thì đó là ajax .. mặc dù, đã nói rằng, ajax đồng nghĩa với xhr, nhưng bản thân nó không mô tả cơ chế / thành phần cơ bản cung cấp / trao đổi tải trọng.
Brett Caswell

4
@BrettCaswell Tôi không nói rằng AJAX / XHR không thể thực hiện được, chỉ là không thể đăng một tập tin với họ trên các phiên bản IEbut cũ của IEbut. Điều đó đã và vẫn hoàn toàn đúng.
Oli

Đây không phải là như thế nào, đây là một ý kiến ​​UX - có thể hợp lệ.
Nimjox

112

Tôi khuyên bạn nên sử dụng plugin Fine Uploader cho mục đích này. JavaScriptMã của bạn sẽ là:

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

Nó sử dụng JSON - vì vậy đối với phiên bản cũ của PHP, nó sẽ không thể sử dụng được.
Lorenzo Manucci

Có vẻ sạch hơn nhiều so với Tải lên tệp Ajax, 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 mới hơn cho phiên bản 2 hiện là valums-file-uploader.github.com/file-uploader
Simon East

35
"Plugin này được mở nguồn theo 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

Tui bỏ lỡ điều gì vậy? Thư viện này dường như không sử dụng jquery nữa, vì vậy nó không hỗ trợ cú pháp từ câu trả lời?
James McCormack

102

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


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


1
Có, bạn có thể POST vào iframe và chụp tệp ở đó. Tôi có rất ít kinh nghiệm với điều này, vì vậy tôi không thể bình luận về nó.
Mattias

15
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/
Đổi

Không được hỗ trợ trong IE9 và ít hơn
Phóng xạ

96

Kết thúc cho độc giả tương lai.

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

Với HTML5

Bạn có thể tải lên các tệp bằng jQuery bằng $.ajax()phương thức nếu FormDataAPI tệp được hỗ trợ (cả hai tính năng HTML5).

Bạn cũng có thể gửi các tệp mà không có FormData nhưng bằng cách nào đó phải xuất hiện API tệp để xử lý các tệp theo cách mà chúng có thể được gửi bằng 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!");
});

Để biết ví dụ JavaScript nhanh, thuần túy ( không có jQuery ), hãy xem " Gửi tệp bằng cách sử dụng đối tượng FormData ".

Dự phòng

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

Nó bao gồm đặt iframe làm mục tiêu của biểu mẫu với các đầu vào 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 iframe thay vì hiển thị lại trang chính. Ẩn iframe làm cho toàn bộ quá trình minh bạch cho 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ố lưu ý như làm thế nào để có được phản hồi từ iframe.

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 , sử dụng kỹ thuật iframe nhưng cũng cung cấp một vận chuyển jQuery Ajax cho phép gửi các tệp chỉ bằng $.ajax()phương thức như sau:

$.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 hỗ trợ dự phòng cho phương pháp ajax của jQuery, nhưng nhiều plugin đã nói ở trên như jQuery Form Plugin hoặc jQuery File Upload bao gồm toàn bộ ngăn xếp từ HTML5 sang 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. 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 triển khai trần hoặc một trong hai plugin này.


3
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 cái này với chrome, loại nội dung biểu mẫu đã bị jQuery vô hiệu.
tro

Câu trả lời tốt đẹp. Một vài gợi ý để cải thiện: Loại bỏ các phần của mã không liên quan đến câu trả lời, ví dụ như .done()và các .fail()cuộc gọi lại. Ngoài ra, một ví dụ không sử dụng FormDatavà danh sách pro / cons sẽ rất tuyệt vời.
Zero3

Tôi đã gặp lỗi này:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
xì phé

85

Tệp AJAX này tải lên plugin jQuery tải lên tệp một số thứ và chuyển phản hồi cho 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ó <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ư -

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

1
@ user840250 jQuery 1.9.1?
Jordan Feldstein

62

Tôi đã sử dụng đoạn script dưới đây để tải lên hình ảnh 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 phản hồi divđể hiển thị hoạt hì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 & vv với tệp khi bạn sử dụng tập lệnh này. Tôi đã đề cập đến nó extra-datanhư trong kịch bản.

Ở cấp độ PHP, nó sẽ hoạt động như tải lên tệp bình thường. dữ liệu bổ sung có thể được lấy ra dưới dạng $_POSTdữ liệu.

Ở đây bạn không sử dụng plugin và công cụ. Bạn có thể thay đổi mã theo ý 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ệp tải lên jQuery nào. Thật ra Javascript.


5
-1 để sử dụng jQuery và không sử dụng công cụ chọn và xử lý sự kiện. addEventListenerkhông phải là trình duyệt chéo.
Đánh dấu

3
Bởi vì sẽ thật vô nghĩa khi thêm một câu trả lời riêng mà chủ yếu dựa trên câu hỏi này, chỉ với một vài thay đổi. Thay vào đó, câu trả lời này nên được sửa chữa.
Đánh dấu

2
@RainFromHeaven, làm ơn, bạn có thể chỉnh sửa câu trả lời không? Tôi không biết làm thế nào để làm điều đó theo cách đa trình duyệt.
Thiago Negri

2
Vẫn không hoạt động trong IE 9 trở xuống. Phân bổ của người dùng vẫn sử dụng các phiên bản IE.
Pierre

1
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ó nó sẽ trông như thế nào?
SamuraiJack

49

Bạn có thể làm điều đó trong JavaScript vanilla khá dễ dàng. Đây là một đoạn trong dự án hiện tại của tôi:

var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
    var percent = (e.position/ e.totalSize);
    // Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
    if(this.readyState === 4) {
        // Handle file upload complete
    }
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);

3
@Gary: Xin lỗi, tôi cũng nên đăng bit đó. Tôi chỉ sử dụng chức năng kéo và thả mới trong HTML5; bạn có thể tìm thấy một ví dụ ở đây: html5demos.com/file-api#view-source - chỉ cần nhấp vào "xem nguồn". Về cơ bản, bên trong ondropsự kiện bạn có thể làmvar file = e.dataTransfer.files[0]
mpen

Có lẽ câu hỏi đã được chỉnh sửa từ đó, nhưng một số người trong cuộc thảo luận tôi đã mở nghĩ rằng câu trả lời của vanilla là lạc đề nếu OP yêu cầu một giải pháp jQuery (với điều kiện là tồn tại) và những câu trả lời như vậy thuộc về một câu hỏi riêng biệt.
Andy

4
@Andy Tôi không đồng ý, và có vẻ như 34 người khác cũng vậy. Nếu bạn có thể sử dụng jQuery, thì bạn chắc chắn có thể sử dụng JavaScript. Trong mọi trường hợp, đây là một trang web cộng đồng - không chỉ OP mà tôi đang cố gắng giúp đỡ ở đây. Mọi người có thể tự do lựa chọn / sử dụng câu trả lời họ thích nhất. Một số người chỉ hấp dẫn về jQuery vì họ nghĩ rằng nó sẽ dễ dàng hơn / ít dòng mã hơn, khi thực sự họ không cần đến một thư viện bổ sung.
mở

47

Bạn có thể tải lên đơn giản với jQuery .ajax().

HTML:

<form id="upload-form">
    <div>
        <label for="file">File:</label>
        <input type="file" id="file" name="file" />
        <progress class="progress" value="0" max="100"></progress>
    </div>
    <hr />
    <input type="submit" value="Submit" />
</form>

CSS

.progress { display: none; }

Javascript:

$(document).ready(function(ev) {
    $("#upload-form").on('submit', (function(ev) {
        ev.preventDefault();
        $.ajax({
            xhr: function() {
                var progress = $('.progress'),
                    xhr = $.ajaxSettings.xhr();

                progress.show();

                xhr.upload.onprogress = function(ev) {
                    if (ev.lengthComputable) {
                        var percentComplete = parseInt((ev.loaded / ev.total) * 100);
                        progress.val(percentComplete);
                        if (percentComplete === 100) {
                            progress.hide().val(0);
                        }
                    }
                };

                return xhr;
            },
            url: 'upload.php',
            type: 'POST',
            data: new FormData(this),
            contentType: false,
            cache: false,
            processData: false,
            success: function(data, status, xhr) {
                // ...
            },
            error: function(xhr, status, error) {
                // ...
            }
       });
    }));
});

1
@RaydenBlack chỉ jQuery.
Zayn Ali

Làm thế nào để có được tiến trình tải lên?
Ali Sherafat

44

Cách đơn giản và mạnh mẽ nhất mà tôi đã làm trong quá khứ, chỉ đơn giản là nhắm mục tiêu thẻ iFrame ẩn với biểu mẫu của bạn - sau đó nó sẽ gửi trong iframe mà không cần tải lại trang.

Đó là nếu bạn không muốn sử dụng plugin, JavaScript hoặc bất kỳ hình thức "ma thuật" nào khác ngoài HTML. Tất nhiên bạn có thể kết hợp điều này với JavaScript hoặc những gì bạn có ...

<form target="iframe" action="" method="post" enctype="multipart/form-data">
    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

<iframe name="iframe" id="iframe" style="display:none" ></iframe>

Bạn cũng có thể đọc nội dung của iframe onLoadcho lỗi máy chủ hoặc phản hồi thành công và sau đó xuất nó cho người dùng.

Chrome, iFrames và onLoad

-note- bạn chỉ cần tiếp tục đọc nếu bạn quan tâm đến cách thiết lập trình chặn UI khi thực hiện tải lên / tải xuống

Hiện tại Chrome không kích hoạt sự kiện onLoad cho iframe khi nó được sử dụng để truyền tệp. Firefox, IE và Edge đều kích hoạt sự kiện onload để truyền tệp.

Giải pháp duy nhất mà tôi thấy hiệu quả với Chrome là sử dụng cookie.

Để làm điều đó về cơ bản khi bắt đầu tải lên / tải xuống:

  • [Phía khách hàng] Bắt đầu một khoảng thời gian để tìm kiếm sự tồn tại của cookie
  • [Phía máy chủ] Làm bất cứ điều gì bạn cần với dữ liệu tệp
  • [Phía máy chủ] Đặt cookie cho khoảng thời gian phía máy khách
  • [Phía khách hàng] Interval nhìn thấy cookie và sử dụng nó như sự kiện onLoad. Ví dụ: bạn có thể khởi động trình chặn UI và sau đó onLoad (hoặc khi cookie được tạo), bạn xóa trình chặn UI.

Sử dụng một cookie cho điều này là xấu xí nhưng nó hoạt động.

Tôi đã tạo một plugin jQuery để xử lý sự cố này cho Chrome khi tải xuống, bạn có thể tìm thấy ở đây

https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDoader.js

Hiệu trưởng cơ bản tương tự cũng được áp dụng để tải lên.

Để sử dụng trình tải xuống (bao gồm cả JS, rõ ràng)

 $('body').iDownloader({
     "onComplete" : function(){
          $('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
     }
 });

 $('somebuttion').click( function(){
      $('#uiBlocker').css('display', 'block'); //block the UI
      $('body').iDownloader('download', 'htttp://example.com/location/of/download');
 });

Và về phía máy chủ, ngay trước khi chuyển dữ liệu tệp, hãy tạo cookie

 setcookie('iDownloader', true, time() + 30, "/");

Plugin sẽ thấy cookie và sau đó kích hoạt onCompletegọi lại.


3
Tôi thích nó. Nếu chỉ có ai đó có thể đề cập đến các vấn đề tiềm năng với giải pháp tuyệt vời này. Tôi thực sự không hiểu tại sao mọi người lại nói thẳng và sử dụng các thư viện và plugin khó hiểu này khi có giải pháp.
Yevgeniy Afanasyev

1
Chà, tôi đoán lý do sẽ là để hiển thị một số thông tin tiến bộ trong khi tải lên.
Prakhar Mishra

32

Một giải pháp tôi tìm thấy là có <form>một iFrame ẩn. IFrame sau đó có thể chạy JS để hiển thị cho người dùng đã hoàn thành (khi tải trang).


1
Tôi quan tâm đến câu trả lời này, bạn có bản demo nào bạn có thể liên kết đến không?
lfender6445

32

Tôi đã viết nó lên trong một môi trường Rails . Đó chỉ là khoảng năm dòng JavaScript, nếu bạn sử dụng plugin dạng jQuery nhẹ.

Thách thức là làm cho tải lên AJAX hoạt động như tiêu chuẩn remote_form_forkhông hiểu việc gửi biểu mẫu nhiều phần. Sẽ không gửi dữ liệu tệp Rails tìm kiếm lại với yêu cầu AJAX.

Đó là nơi mà plugin dạng jQuery phát huy tác dụng.

Đây là mã Rails cho nó:

<% remote_form_for(:image_form, 
                   :url => { :controller => "blogs", :action => :create_asset }, 
                   :html => { :method => :post, 
                              :id => 'uploadForm', :multipart => true }) 
                                                                        do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

Đây là JavaScript liên quan:

$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
  beforeSubmit: function(a,f,o) {
   o.dataType = 'json';
  },
  complete: function(XMLHttpRequest, textStatus) {
   // XMLHttpRequest.responseText will contain the URL of the uploaded image.
   // Put it in an image element you create, or do with it what you will.
   // For example, if you have an image elemtn with id "my_image", then
   //  $('#my_image').attr('src', XMLHttpRequest.responseText);
   // Will set that image tag to display the uploaded image.
  },
 });
});

Và đây là hành động của bộ điều khiển Rails, vanilla đẹp:

 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

Tôi đã sử dụng điều này trong vài tuần qua với Bloggity và nó hoạt động như một nhà vô địch.


31

Trình tải lên Ajax đơn giản là một tùy chọn khác:

https://github.com/LPology/Simple-Ajax-Uploader

  • Trình duyệt chéo - hoạt động trong IE7 +, Firefox, Chrome, Safari, Opera
  • Hỗ trợ nhiều, tải lên đồng thời - ngay cả trong các trình duyệt không phải là HTML5
  • Không có flash hoặc CSS bên ngoài - chỉ có một tệp Javascript 5Kb
  • Tùy chọn, hỗ trợ tích hợp cho các thanh tiến trình trình duyệt chéo hoàn toàn (sử dụng tiện ích mở rộng APC của PHP)
  • Linh hoạt và tùy biến cao - sử dụng bất kỳ yếu tố nào làm nút tải lên, tạo kiểu cho các chỉ số tiến trình của riêng bạn
  • Không cần biểu mẫu, chỉ cần cung cấp một yếu tố sẽ đóng vai trò là nút tải lên
  • Giấy phép MIT - miễn phí sử dụng trong dự án thương mại

Ví dụ sử dụng:

var uploader = new ss.SimpleUpload({
    button: $('#uploadBtn'), // upload button
    url: '/uploadhandler', // URL of server-side upload handler
    name: 'userfile', // parameter name of the uploaded file
    onSubmit: function() {
        this.setProgressBar( $('#progressBar') ); // designate elem as our progress bar
    },
    onComplete: function(file, response) {
        // do whatever after upload is finished
    }
});

2
Đây dường như là hứa hẹn nhất cho đến nay, Bạn đã cho tôi tại IE7+! Dùng thử ngay bây giờ. Cảm ơn
Pierre

25

jQuery Uploadify là một plugin tốt khác mà tôi đã sử dụng trước đây để tải lên các tệp. Mã JavaScript đơn giản như sau: mã. Tuy nhiên, phiên bản mới không hoạt động trong Internet Explorer.

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

Tôi đã thực hiện rất nhiều tìm kiếm và tôi đã đi đến một giải pháp khác để tải lên các tệp mà không cần bất kỳ plugin nào và chỉ với ajax. Giải pháp như sau:

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}

2
Uploadify đã chết trong nhiều năm. Không được hỗ trợ hoặc duy trì nữa.
Ray Nicholus

24

Đây chỉ là một giải pháp khác về cách tải lên tệp ( không có bất kỳ plugin nào )

Sử dụng JavascriptsAJAX đơn giản (có thanh tiến trình)

Phần HTML

<form id="upload_form" enctype="multipart/form-data" method="post">
    <input type="file" name="file1" id="file1"><br>
    <input type="button" value="Upload File" onclick="uploadFile()">
    <progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
    <h3 id="status"></h3>
    <p id="loaded_n_total"></p>
</form>

Phần JS

function _(el){
    return document.getElementById(el);
}
function uploadFile(){
    var file = _("file1").files[0];
    // alert(file.name+" | "+file.size+" | "+file.type);
    var formdata = new FormData();
    formdata.append("file1", file);
    var ajax = new XMLHttpRequest();
    ajax.upload.addEventListener("progress", progressHandler, false);
    ajax.addEventListener("load", completeHandler, false);
    ajax.addEventListener("error", errorHandler, false);
    ajax.addEventListener("abort", abortHandler, false);
    ajax.open("POST", "file_upload_parser.php");
    ajax.send(formdata);
}
function progressHandler(event){
    _("loaded_n_total").innerHTML = "Uploaded "+event.loaded+" bytes of "+event.total;
    var percent = (event.loaded / event.total) * 100;
    _("progressBar").value = Math.round(percent);
    _("status").innerHTML = Math.round(percent)+"% uploaded... please wait";
}
function completeHandler(event){
    _("status").innerHTML = event.target.responseText;
    _("progressBar").value = 0;
}
function errorHandler(event){
    _("status").innerHTML = "Upload Failed";
}
function abortHandler(event){
    _("status").innerHTML = "Upload Aborted";
}

Phần PHP

<?php
$fileName = $_FILES["file1"]["name"]; // The file name
$fileTmpLoc = $_FILES["file1"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["file1"]["type"]; // The type of file it is
$fileSize = $_FILES["file1"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["file1"]["error"]; // 0 for false... and 1 for true
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
}
if(move_uploaded_file($fileTmpLoc, "test_uploads/$fileName")){ // assuming the directory name 'test_uploads'
    echo "$fileName upload is complete";
} else {
    echo "move_uploaded_file function failed";
}
?>

Đây là ứng dụng VÍ DỤ


19
var formData=new FormData();
formData.append("fieldname","value");
formData.append("image",$('[name="filename"]')[0].files[0]);

$.ajax({
    url:"page.php",
    data:formData,
    type: 'POST',
    dataType:"JSON",
    cache: false,
    contentType: false,
    processData: false,
    success:function(data){ }
});

Bạn có thể sử dụng dữ liệu biểu mẫu để đăng tất cả các giá trị của bạn bao gồm cả hình ảnh.


6
Lưu ý: cache: falselà dự phòng theo POSTyêu cầu vì POST không bao giờ lưu trữ.
Mã hóa

@Vivek Aasaithambi, tôi đã gặp lỗi này:TypeError: Argument 1 of FormData.constructor does not implement interface HTMLFormElement.
nến

15

Để tải lên tệp không đồng bộ với Jquery, hãy sử dụng các bước bên dưới:

Bước 1 Trong dự án của bạn, hãy mở trình quản lý Nuget và thêm gói (tải tập tin jquery (chỉ cần bạn viết nó vào hộp tìm kiếm, nó sẽ xuất hiện và cài đặt nó.)) URL: https://github.com/blueimp/jQuery-File- Tải lên

Bước 2 Thêm các tập lệnh bên dưới trong các tệp HTML, đã được thêm vào dự án bằng cách chạy gói trên:

jquery.ui.widget.js

jquery.iframe-Transport.js

jquery.fileupload.js

Bước 3 Viết kiểm soát tải lên tệp theo mã dưới đây:

<input id="upload" name="upload" type="file" />

Bước 4 viết phương thức js là uploadFile như sau:

 function uploadFile(element) {

            $(element).fileupload({

                dataType: 'json',
                url: '../DocumentUpload/upload',
                autoUpload: true,
                add: function (e, data) {           
                  // write code for implementing, while selecting a file. 
                  // data represents the file data. 
                  //below code triggers the action in mvc controller
                  data.formData =
                                    {
                                     files: data.files[0]
                                    };
                  data.submit();
                },
                done: function (e, data) {          
                   // after file uploaded
                },
                progress: function (e, data) {

                   // progress
                },
                fail: function (e, data) {

                   //fail operation
                },
                stop: function () {

                  code for cancel operation
                }
            });

        };

Bước 5 Trong chức năng sẵn sàng tải lên tệp phần tử gọi để bắt đầu quá trình như dưới đây:

$(document).ready(function()
{
    uploadFile($('#upload'));

});

Bước 6 Viết trình điều khiển MVC và Hành động theo bên dưới:

public class DocumentUploadController : Controller
    {       

        [System.Web.Mvc.HttpPost]
        public JsonResult upload(ICollection<HttpPostedFileBase> files)
        {
            bool result = false;

            if (files != null || files.Count > 0)
            {
                try
                {
                    foreach (HttpPostedFileBase file in files)
                    {
                        if (file.ContentLength == 0)
                            throw new Exception("Zero length file!");                       
                        else 
                            //code for saving a file

                    }
                }
                catch (Exception)
                {
                    result = false;
                }
            }


            return new JsonResult()
                {
                    Data=result
                };


        }

    }

14

Một cách tiếp cận hiện đại mà không có Jquery là sử dụng đối tượng FileList mà bạn nhận được <input type="file">khi người dùng chọn (các) tệp và sau đó sử dụng Fetch để đăng FileList được bao quanh đối tượng FormData .

// The input DOM element // <input type="file">
const inputElement = document.querySelector('input[type=file]');

// Listen for a file submit from user
inputElement.addEventListener('change', () => {
    const data = new FormData();
    data.append('file', inputElement.files[0]);
    data.append('imageName', 'flower');

    // You can then post it to your server.
    // Fetch can accept an object of type FormData on its  body
    fetch('/uploadImage', {
        method: 'POST',
        body: data
    });
});

Rõ ràng không được hỗ trợ trên IE
Marco Demaio

11

Bạn có thể thấy một giải pháp đã được giải quyết với bản demo hoạt động ở đây cho phép bạn xem trước và gửi tệp biểu mẫu đến máy chủ. Đối với trường hợp của bạn, bạn cần sử dụng Ajax để tạo điều kiện cho tệp tải lên máy chủ:

<from action="" id="formContent" method="post" enctype="multipart/form-data">
    <span>File</span>
    <input type="file" id="file" name="file" size="10"/>
    <input id="uploadbutton" type="button" value="Upload"/>
</form>

Dữ liệu được gửi là một formdata. Trên jQuery của bạn, sử dụng hàm gửi biểu mẫu thay vì nhấp vào nút để gửi tệp biểu mẫu như dưới đây.

$(document).ready(function () {
   $("#formContent").submit(function(e){

     e.preventDefault();
     var formdata = new FormData(this);

 $.ajax({
     url: "ajax_upload_image.php",
     type: "POST",
     data: formdata,
     mimeTypes:"multipart/form-data",
     contentType: false,
     cache: false,
     processData: false,
     success: function(){

     alert("successfully submitted");

     });
   });
});

Xem thêm chi tiết


11

Ví dụ: Nếu bạn sử dụng jQuery, bạn có thể dễ dàng tải lên tệp. Đây là một plugin jQuery nhỏ và mạnh, http://jquery.malsup.com/form/ .

Thí dụ

var $bar   = $('.ProgressBar');
$('.Form').ajaxForm({
  dataType: 'json',

  beforeSend: function(xhr) {
    var percentVal = '0%';
    $bar.width(percentVal);
  },

  uploadProgress: function(event, position, total, percentComplete) {
    var percentVal = percentComplete + '%';
    $bar.width(percentVal)
  },

  success: function(response) {
    // Response
  }
});

Tôi hy vọng nó sẽ hữu ích


10

Bạn có thể dùng

$(function() {
    $("#file_upload_1").uploadify({
        height        : 30,
        swf           : '/uploadify/uploadify.swf',
        uploader      : '/uploadify/uploadify.php',
        width         : 120
    });
});

Bản giới thiệu


9

Chuyển đổi tệp thành base64 bằng cách sử dụng | HTML5As readAsDataURL () hoặc một số bộ mã hóa base64 . Fiddle ở đây

var reader = new FileReader();

        reader.onload = function(readerEvt) {
            var binaryString = readerEvt.target.result;
            document.getElementById("base64textarea").value = btoa(binaryString);
        };

        reader.readAsBinaryString(file);

Sau đó để lấy:

window.open("data:application/octet-stream;base64," + base64);

9

Bạn có thể chuyển các tham số bổ sung cùng với tên tệp khi thực hiện tải lên không đồng bộ bằng cách sử dụng XMLHttpRequest (không có phụ thuộc flash và iframe). Nối giá trị tham số bổ sung với FormData và gửi yêu cầu tải lên.


var formData = new FormData();
formData.append('parameter1', 'value1');
formData.append('parameter2', 'value2'); 
formData.append('file', $('input[type=file]')[0].files[0]);

$.ajax({
    url: 'post back url',
    data: formData,
// other attributes of AJAX
});

Ngoài ra, tải lên tệp UI Syncfusion JavaScript cung cấp giải pháp cho tình huống này chỉ bằng cách sử dụng đối số sự kiện. bạn có thể tìm tài liệu ở đây và biết thêm chi tiết về điều khiển này tại đây, nhập mô tả liên kết tại đây


8

Tìm kiếm Xử lý quá trình tải lên cho một tệp, không đồng bộ tại đây: https://developer.mozilla.org/en-US/docs/Using_files_from_web_appluggest

Mẫu từ liên kết

<?php
if (isset($_FILES['myFile'])) {
    // Example:
    move_uploaded_file($_FILES['myFile']['tmp_name'], "uploads/" . $_FILES['myFile']['name']);
    exit;
}
?><!DOCTYPE html>
<html>
<head>
    <title>dnd binary upload</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript">
        function sendFile(file) {
            var uri = "/index.php";
            var xhr = new XMLHttpRequest();
            var fd = new FormData();

            xhr.open("POST", uri, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    // Handle response.
                    alert(xhr.responseText); // handle response.
                }
            };
            fd.append('myFile', file);
            // Initiate a multipart/form-data upload
            xhr.send(fd);
        }

        window.onload = function() {
            var dropzone = document.getElementById("dropzone");
            dropzone.ondragover = dropzone.ondragenter = function(event) {
                event.stopPropagation();
                event.preventDefault();
            }

            dropzone.ondrop = function(event) {
                event.stopPropagation();
                event.preventDefault();

                var filesArray = event.dataTransfer.files;
                for (var i=0; i<filesArray.length; i++) {
                    sendFile(filesArray[i]);
                }
            }
        }
    </script>
</head>
<body>
    <div>
        <div id="dropzone" style="margin:30px; width:500px; height:300px; border:1px dotted grey;">Drag & drop your file here...</div>
    </div>
</body>
</html>

7

Đây là giải pháp của tôi.

<form enctype="multipart/form-data">    

    <div class="form-group">
        <label class="control-label col-md-2" for="apta_Description">Description</label>
        <div class="col-md-10">
            <input class="form-control text-box single-line" id="apta_Description" name="apta_Description" type="text" value="">
        </div>
    </div>

    <input name="file" type="file" />
    <input type="button" value="Upload" />
</form>

và js

<script>

    $(':button').click(function () {
        var formData = new FormData($('form')[0]);
        $.ajax({
            url: '@Url.Action("Save", "Home")',  
            type: 'POST',                
            success: completeHandler,
            data: formData,
            cache: false,
            contentType: false,
            processData: false
        });
    });    

    function completeHandler() {
        alert(":)");
    }    
</script>

Bộ điều khiển

[HttpPost]
public ActionResult Save(string apta_Description, HttpPostedFileBase file)
{
    [...]
}

2
Bạn dường như đã trộn một số loại khung vào câu trả lời của bạn. Ít nhất, bạn nên đề cập đến khung mà câu trả lời của bạn có thể sử dụng được. Tốt hơn nữa, loại bỏ tất cả các công cụ khung và chỉ đưa ra một câu trả lời cho câu hỏi được đặt ra.
Zero3

2
Vì vậy, thực sự có một khung mvc gọi là "mvc"? và nó sử dụng cú pháp csharpish? Thật tàn nhẫn.
nonchip

6

Sử dụng HTML5JavaScript , tải lên async khá dễ dàng, tôi tạo logic tải lên cùng với html của bạn, điều này không hoạt động đầy đủ vì nó cần api, nhưng hãy chứng minh cách nó hoạt động, nếu bạn có điểm cuối được gọi /uploadtừ gốc của trang web, mã này sẽ làm việc cho bạn:

const asyncFileUpload = () => {
  const fileInput = document.getElementById("file");
  const file = fileInput.files[0];
  const uri = "/upload";
  const xhr = new XMLHttpRequest();
  xhr.upload.onprogress = e => {
    const percentage = e.loaded / e.total;
    console.log(percentage);
  };
  xhr.onreadystatechange = e => {
    if (xhr.readyState === 4 && xhr.status === 200) {
      console.log("file uploaded");
    }
  };
  xhr.open("POST", uri, true);
  xhr.setRequestHeader("X-FileName", file.name);
  xhr.send(file);
}
<form>
  <span>File</span>
  <input type="file" id="file" name="file" size="10" />
  <input onclick="asyncFileUpload()" id="upload" type="button" value="Upload" />
</form>

Ngoài ra một số thông tin khác về XMLHttpReques:

Đối tượng XMLHttpRequest

Tất cả các trình duyệt hiện đại đều hỗ trợ đối tượng XMLHttpRequest. Đối tượng XMLHttpRequest có thể được sử dụng để trao đổi dữ liệu với máy chủ web phía sau hậu trường. Điều này có nghĩa là có thể cập nhật các phần của trang web mà không cần tải lại toàn bộ trang.


Tạo một đối tượng XMLHttpRequest

Tất cả các trình duyệt hiện đại (Chrome, Firefox, IE7 +, Edge, Safari, Opera) đều có một đối tượng XMLHttpRequest tích hợp.

Cú pháp để tạo một đối tượng XMLHttpRequest:

biến = new XMLHttpRequest ();


Truy cập trên toàn miền

Vì lý do bảo mật, các trình duyệt hiện đại không cho phép truy cập trên các miền.

Điều này có nghĩa là cả trang web và tệp XML mà nó cố tải, phải được đặt trên cùng một máy chủ.

Các ví dụ trên W3Schools tất cả các tệp XML mở nằm trên miền W3Schools.

Nếu bạn muốn sử dụng ví dụ trên trên một trong các trang web của riêng bạn, các tệp XML bạn tải phải được đặt trên máy chủ của riêng bạn.

Để biết thêm chi tiết, bạn có thể tiếp tục đọc tại đây ...


5

Bạn có thể sử dụng API tìm nạp mới hơn bằng JavaScript. Như thế này:

function uploadButtonCLicked(){
    var input = document.querySelector('input[type="file"]')

    fetch('/url', {
      method: 'POST',
      body: input.files[0]
    }).then(res => res.json())   // you can do something with response
      .catch(error => console.error('Error:', error))
      .then(response => console.log('Success:', response));
}                               

Ưu điểm: API tìm nạp được hỗ trợ bởi tất cả các trình duyệt hiện đại, do đó bạn không phải nhập bất cứ thứ gì. Ngoài ra, lưu ý rằng fetch () trả về một Promise sau đó được xử lý bằng cách sử dụng .then(..code to handle response..)không đồng bộ.


4

Bạn có thể thực hiện tải lên nhiều tệp không đồng bộ bằng JavaScript hoặc jQuery và không cần sử dụng bất kỳ plugin nào. Bạn cũng có thể hiển thị tiến trình tải lên tập tin theo thời gian thực trong điều khiển tiến trình. Tôi đã đi qua 2 liên kết tốt đẹp -

  1. ASP.NET Web Forms dựa trên tính năng tải lên tệp Mulitple với thanh tiến trình
  2. ASP.NET MVC dựa trên nhiều tệp Tải lên được thực hiện trong jQuery

Ngôn ngữ phía máy chủ là C # nhưng bạn có thể thực hiện một số sửa đổi để làm cho nó hoạt động với ngôn ngữ khác như PHP.

Tải lên tệp ASP.NET Core MVC:

Trong phần Xem điều khiển tải lên tệp trong html:

<form method="post" asp-action="Add" enctype="multipart/form-data">
    <input type="file" multiple name="mediaUpload" />
    <button type="submit">Submit</button>
</form>

Bây giờ tạo phương thức hành động trong bộ điều khiển của bạn:

[HttpPost]
public async Task<IActionResult> Add(IFormFile[] mediaUpload)
{
    //looping through all the files
    foreach (IFormFile file in mediaUpload)
    {
        //saving the files
        string path = Path.Combine(hostingEnvironment.WebRootPath, "some-folder-path"); 
        using (var stream = new FileStream(path, FileMode.Create))
        {
            await file.CopyToAsync(stream);
        }
    }
}

Biến hostingEn Môi trường thuộc loại IhostingEn Môi trường có thể được tiêm vào bộ điều khiển bằng cách sử dụng phép nội xạ phụ thuộc, như:

private IHostingEnvironment hostingEnvironment;
public MediaController(IHostingEnvironment environment)
{
    hostingEnvironment = environment;
}

Bạn có thể bao gồm bản chất của giải pháp trong câu trả lời của mình không, vì nếu không nó có thể trở nên vô dụng nếu trang web được liên kết thay đổi hoặc ngoại tuyến.
Dima Kozhevin

4

Đối với PHP, hãy tìm https://developer.hyvor.com/php/image-upload-ajax-php-mysql

HTML

<html>
<head>
    <title>Image Upload with AJAX, PHP and MYSQL</title>
</head>
<body>
<form onsubmit="submitForm(event);">
    <input type="file" name="image" id="image-selecter" accept="image/*">
    <input type="submit" name="submit" value="Upload Image">
</form>
<div id="uploading-text" style="display:none;">Uploading...</div>
<img id="preview">
</body>
</html>

JAVASCRIPT

var previewImage = document.getElementById("preview"),  
    uploadingText = document.getElementById("uploading-text");

function submitForm(event) {
    // prevent default form submission
    event.preventDefault();
    uploadImage();
}

function uploadImage() {
    var imageSelecter = document.getElementById("image-selecter"),
        file = imageSelecter.files[0];
    if (!file) 
        return alert("Please select a file");
    // clear the previous image
    previewImage.removeAttribute("src");
    // show uploading text
    uploadingText.style.display = "block";
    // create form data and append the file
    var formData = new FormData();
    formData.append("image", file);
    // do the ajax part
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function() {
        if (this.readyState === 4 && this.status === 200) {
            var json = JSON.parse(this.responseText);
            if (!json || json.status !== true) 
                return uploadError(json.error);

            showImage(json.url);
        }
    }
    ajax.open("POST", "upload.php", true);
    ajax.send(formData); // send the form data
}

PHP

<?php
$host = 'localhost';
$user = 'user';
$password = 'password';
$database = 'database';
$mysqli = new mysqli($host, $user, $password, $database);


 try {
    if (empty($_FILES['image'])) {
        throw new Exception('Image file is missing');
    }
    $image = $_FILES['image'];
    // check INI error
    if ($image['error'] !== 0) {
        if ($image['error'] === 1) 
            throw new Exception('Max upload size exceeded');

        throw new Exception('Image uploading error: INI Error');
    }
    // check if the file exists
    if (!file_exists($image['tmp_name']))
        throw new Exception('Image file is missing in the server');
    $maxFileSize = 2 * 10e6; // in bytes
    if ($image['size'] > $maxFileSize)
        throw new Exception('Max size limit exceeded'); 
    // check if uploaded file is an image
    $imageData = getimagesize($image['tmp_name']);
    if (!$imageData) 
        throw new Exception('Invalid image');
    $mimeType = $imageData['mime'];
    // validate mime type
    $allowedMimeTypes = ['image/jpeg', 'image/png', 'image/gif'];
    if (!in_array($mimeType, $allowedMimeTypes)) 
        throw new Exception('Only JPEG, PNG and GIFs are allowed');

    // nice! it's a valid image
    // get file extension (ex: jpg, png) not (.jpg)
    $fileExtention = strtolower(pathinfo($image['name'] ,PATHINFO_EXTENSION));
    // create random name for your image
    $fileName = round(microtime(true)) . mt_rand() . '.' . $fileExtention; // anyfilename.jpg
    // Create the path starting from DOCUMENT ROOT of your website
    $path = '/examples/image-upload/images/' . $fileName;
    // file path in the computer - where to save it 
    $destination = $_SERVER['DOCUMENT_ROOT'] . $path;

    if (!move_uploaded_file($image['tmp_name'], $destination))
        throw new Exception('Error in moving the uploaded file');

    // create the url
    $protocol = stripos($_SERVER['SERVER_PROTOCOL'],'https') === true ? 'https://' : 'http://';
    $domain = $protocol . $_SERVER['SERVER_NAME'];
    $url = $domain . $path;
    $stmt = $mysqli -> prepare('INSERT INTO image_uploads (url) VALUES (?)');
    if (
        $stmt &&
        $stmt -> bind_param('s', $url) &&
        $stmt -> execute()
    ) {
        exit(
            json_encode(
                array(
                    'status' => true,
                    'url' => $url
                )
            )
        );
    } else 
        throw new Exception('Error in saving into the database');

} catch (Exception $e) {
    exit(json_encode(
        array (
            'status' => false,
            'error' => $e -> getMessage()
        )
    ));
}

4

Bạn cũng có thể xem xét sử dụng một cái gì đó như https://uppy.io .

Nó không tải lên tệp mà không điều hướng khỏi trang và cung cấp một số phần thưởng như kéo và thả, tiếp tục tải lên trong trường hợp trình duyệt gặp sự cố / mạng không ổn định và nhập từ ví dụ Instagram. Nó là nguồn mở và không dựa vào jQuery / React / Angular / Vue, nhưng có thể được sử dụng với nó. Tuyên bố miễn trừ trách nhiệm: với tư cách là người tạo ra nó, tôi thiên vị;)


Liên kết ở trên là chết. Đây là github: github.com/transloadit/uppy
Chris Charles

uppy.io là các trang CloudFlare + GitHub được hỗ trợ và cho tôi? Vẫn hữu ích khi có liên kết repo trực tiếp nữa :)
kvz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.