Làm thế nào để phát hiện khi hủy được nhấp vào đầu vào tệp?


112

Làm cách nào tôi có thể phát hiện khi người dùng hủy đầu vào tệp bằng đầu vào tệp html?

onChange cho phép tôi phát hiện khi nào họ chọn tệp, nhưng tôi cũng muốn biết khi nào họ hủy (đóng hộp thoại chọn tệp mà không chọn bất kỳ thứ gì).


Bạn cũng có thể phát hiện nếu một người nào đó chọn tập tin và sau đó cố gắng chọn gửi một nhưng hủy bỏ, bạn sẽ nhận được sản phẩm nàoe.target.files
jcubic

Câu trả lời:


45

Mặc dù không phải là một giải pháp trực tiếp, và cũng tệ ở chỗ nó chỉ hoạt động (theo như tôi đã thử nghiệm) hoạt động với onfocus (yêu cầu chặn sự kiện khá hạn chế), bạn có thể đạt được nó bằng cách sau:

document.body.onfocus = function(){ /*rock it*/ }

Điều thú vị về điều này là bạn có thể đính kèm / tách nó ra kịp thời với sự kiện tệp và nó cũng có vẻ hoạt động tốt với các đầu vào ẩn (một đặc quyền nhất định nếu bạn đang sử dụng giải pháp trực quan cho kiểu nhập mặc định tồi tàn = ' tập tin'). Sau đó, bạn chỉ cần tìm xem giá trị đầu vào có thay đổi hay không.

Một ví dụ:

var godzilla = document.getElementById('godzilla')

godzilla.onclick = charge

function charge()
{
    document.body.onfocus = roar
    console.log('chargin')
}

function roar()
{
    if(godzilla.value.length) alert('ROAR! FILES!')
    else alert('*empty wheeze*')
    document.body.onfocus = null
    console.log('depleted')
}

Xem nó trong thực tế: http://jsfiddle.net/Shiboe/yuK3r/6/

Đáng buồn thay, nó dường như chỉ hoạt động trên các trình duyệt webkit. Có thể ai đó khác có thể tìm ra giải pháp firefox / IE


Tôi không muốn sự kiện tiêu điểm phát hỏa mọi lúc, vì vậy tôi muốn sử dụng addEventListener("focus",fn,{once: true}). Tuy nhiên tôi không thể làm cho nó cháy được cả khi sử dụng document.body.addEventListener.. Tôi không biết tại sao. Thay vào đó, tôi nhận được cùng một kết quả với window.addEventListener.
WoodenKitty

3
Điều này không hoạt động trong Firefox và Edge đối với tôi. Tuy nhiên, việc lắng nghe mousemovesự kiện window.document ngoài việc lắng nghe focustrên windowdường như hoạt động ở mọi nơi (ít nhất là trong các trình duyệt hiện đại, tôi không quan tâm đến những tàn tích của thập kỷ trước). Về cơ bản, bất kỳ sự kiện tương tác nào cũng có thể được sử dụng cho tác vụ này bị chặn bởi hộp thoại mở tệp đã mở.
John Weisz

@WoodenKitty bạn đã triển khai điều này như thế nào bằng addEventListener. Tôi đang cố gắng làm điều này trong góc cạnh và tài liệu. Ai đó cũng không làm việc cho tôi
Terrance Jackson

điều này không hoạt động trên các trường nhập ẩn.
Sebastian

20

Bạn không thể.

Kết quả của hộp thoại tệp không được hiển thị cho trình duyệt.


Có thể kiểm tra xem trình chọn tệp có đang mở hay không?
Ppp

1
@Ppp - Không. Trình duyệt không cho bạn biết điều đó.
Oded

6
"Kết quả của hộp thoại tệp không được hiển thị cho trình duyệt." Điều này không đúng nếu hộp thoại được đóng bằng cách chọn một tệp.
Trevor

3
Các thay đổi kích hoạt bằng cách sử dụng hộp thoại tập tin được tiếp xúc với các trình duyệt. Hãy xem, nếu không có tệp nào được chọn và không có tệp nào được chọn sau đó, thì không có gì thay đổi, do đó không có changesự kiện nào được gửi đi.
John Weisz

1
Ngoài ra, nếu một tệp đã được chọn và bạn chọn lại chính tệp đó, thì sẽ không có changesự kiện nào được thực hiện cho tệp đó.
Patrick Roberts

16

Vì vậy, tôi sẽ ngả mũ trước câu hỏi này vì tôi đã nghĩ ra một giải pháp mới. Tôi có một Ứng dụng web tiến bộ cho phép người dùng chụp ảnh và quay video và tải chúng lên. Chúng tôi sử dụng WebRTC khi có thể, nhưng quay lại trình chọn tệp HTML5 cho các thiết bị ít hỗ trợ hơn * ho Safari ho *. Nếu bạn đang làm việc cụ thể trên một ứng dụng web di động Android / iOS sử dụng camera gốc để chụp ảnh / quay video trực tiếp, thì đây là giải pháp tốt nhất mà tôi đã thử.

Điểm mấu chốt của vấn đề này là khi trang tải, hiện tại filenull, nhưng sau đó khi người dùng mở hộp thoại và nhấn "Hủy", filevẫn là null, do đó nó không "thay đổi", do đó không có sự kiện "thay đổi" nào được kích hoạt. Đối với máy tính để bàn, điều này không quá tệ vì hầu hết giao diện người dùng của máy tính để bàn không phụ thuộc vào việc biết khi nào hủy được gọi, nhưng giao diện người dùng di động đưa máy ảnh lên để chụp ảnh / video thì rất phụ thuộc nhiều vào việc biết khi nào nhấn hủy.

Ban đầu tôi đã sử dụng document.body.onfocus sự kiện để phát hiện thời điểm người dùng quay lại từ bộ chọn tệp và điều này hoạt động với hầu hết các thiết bị, nhưng iOS 11.3 đã phá vỡ nó vì sự kiện đó không được kích hoạt.

Ý tưởng

Giải pháp của tôi cho điều này là * shudder * để đo thời gian CPU để xác định xem trang hiện đang ở nền trước hay nền sau. Trên thiết bị di động, thời gian xử lý được cấp cho ứng dụng hiện ở nền trước. Khi camera hiển thị, nó sẽ đánh cắp thời gian của CPU và làm mất tác dụng của trình duyệt. Tất cả những gì chúng ta cần làm là đo lượng thời gian xử lý trang của chúng ta được cung cấp, khi máy ảnh khởi chạy, thời gian khả dụng của chúng ta sẽ giảm đáng kể. Khi máy ảnh bị loại bỏ (hoặc bị hủy hoặc bằng cách khác), thời gian có sẵn của chúng tôi sẽ tăng đột biến.

Thực hiện

Chúng ta có thể đo thời gian của CPU bằng cách sử dụng setTimeout()để gọi một lệnh gọi lại trong X mili giây, sau đó đo thời gian thực sự gọi nó. Trình duyệt sẽ không bao giờ gọi nó chính xác sau X mili giây, nhưng nếu nó đóng hợp lý thì chúng ta phải ở phía trước. Nếu trình duyệt ở rất xa (chậm hơn 10 lần so với yêu cầu) thì chúng tôi phải ở trong nền. Cách triển khai cơ bản của điều này là như vậy:

function waitForCameraDismiss() {
  const REQUESTED_DELAY_MS = 25;
  const ALLOWED_MARGIN_OF_ERROR_MS = 25;
  const MAX_REASONABLE_DELAY_MS =
      REQUESTED_DELAY_MS + ALLOWED_MARGIN_OF_ERROR_MS;
  const MAX_TRIALS_TO_RECORD = 10;

  const triggerDelays = [];
  let lastTriggerTime = Date.now();

  return new Promise((resolve) => {
    const evtTimer = () => {
      // Add the time since the last run
      const now = Date.now();
      triggerDelays.push(now - lastTriggerTime);
      lastTriggerTime = now;

      // Wait until we have enough trials before interpreting them.
      if (triggerDelays.length < MAX_TRIALS_TO_RECORD) {
        window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
        return;
      }

      // Only maintain the last few event delays as trials so as not
      // to penalize a long time in the camera and to avoid exploding
      // memory.
      if (triggerDelays.length > MAX_TRIALS_TO_RECORD) {
        triggerDelays.shift();
      }

      // Compute the average of all trials. If it is outside the
      // acceptable margin of error, then the user must have the
      // camera open. If it is within the margin of error, then the
      // user must have dismissed the camera and returned to the page.
      const averageDelay =
          triggerDelays.reduce((l, r) => l + r) / triggerDelays.length
      if (averageDelay < MAX_REASONABLE_DELAY_MS) {
        // Beyond any reasonable doubt, the user has returned from the
        // camera
        resolve();
      } else {
        // Probably not returned from camera, run another trial.
        window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
      }
    };
    window.setTimeout(evtTimer, REQUESTED_DELAY_MS);
  });
}

Tôi đã thử nghiệm điều này trên phiên bản iOS và Android gần đây, đưa camera gốc lên bằng cách thiết lập các thuộc tính trên <input />phần tử.

<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />

Điều này thực sự diễn ra tốt hơn rất nhiều so với tôi mong đợi. Nó chạy 10 lần thử nghiệm bằng cách yêu cầu bộ đếm thời gian được gọi trong 25 mili giây. Sau đó, nó đo lường thời gian thực sự để gọi ra và nếu trung bình của 10 lần thử nghiệm là dưới 50 mili giây, chúng tôi giả định rằng chúng tôi phải ở phía trước và máy ảnh đã biến mất. Nếu nó lớn hơn 50 mili giây, thì chúng ta vẫn phải ở chế độ nền và nên tiếp tục đợi.

Một số chi tiết bổ sung

Tôi đã sử dụng setTimeout()chứ không phải setInterval()vì cái sau có thể xếp hàng nhiều lệnh gọi thực thi ngay sau nhau. Điều này có thể làm tăng đáng kể nhiễu trong dữ liệu của chúng tôi, vì vậy tôi mắc kẹt vớisetTimeout() mặc dù nó phức tạp hơn một chút để làm như vậy.

Những con số cụ thể này hoạt động tốt đối với tôi, mặc dù tôi đã ít nhất một lần thấy trường hợp loại bỏ camera được phát hiện sớm. Tôi tin rằng điều này là do máy ảnh có thể mở chậm và thiết bị có thể chạy 10 lần thử trước khi thực sự ở chế độ nền. Thêm nhiều thử nghiệm hơn hoặc đợi khoảng 25-50 mili giây trước khi bắt đầu chức năng này có thể là một cách giải quyết cho điều đó.

Máy tính để bàn

Thật không may, điều này không thực sự hoạt động cho các trình duyệt trên máy tính để bàn. Về lý thuyết, thủ thuật tương tự cũng có thể xảy ra vì chúng ưu tiên trang hiện tại hơn các trang nền. Tuy nhiên, nhiều máy tính để bàn có đủ tài nguyên để giữ trang chạy ở tốc độ tối đa ngay cả khi ở chế độ nền, vì vậy chiến lược này không thực sự hiệu quả trong thực tế.

Các giải pháp thay thế

Một giải pháp thay thế mà không nhiều người đề cập đến mà tôi đã khám phá là chế nhạo a FileList. Chúng tôi bắt đầu với nulltrong <input />và sau đó nếu người dùng mở máy ảnh và hủy bỏ họ trở lại null, mà không phải là một sự thay đổi và không có sự kiện sẽ kích hoạt. Một giải pháp sẽ là gán một tệp giả cho <input />ở đầu trang, do đó cài đặt thành nullsẽ là một thay đổi sẽ kích hoạt sự kiện thích hợp.

Thật không may, không có cách nào chính thức để tạo một FileList, và <input />phần tử yêu cầu một FileListđặc biệt và sẽ không chấp nhận bất kỳ giá trị nào khác bên cạnh đó null. Đương nhiên, FileListcác đối tượng không thể được xây dựng trực tiếp, làm cho một số vấn đề bảo mật cũ mà dường như không còn liên quan nữa. Cách duy nhất để có được một <input />phần tử bên ngoài một phần tử là sử dụng một bản hack sao chép dữ liệu để giả mạo sự kiện khay nhớ tạm có thể chứaFileList đối tượng (về cơ bản bạn đang giả mạo tệp kéo và thả -sự kiện trang web của bạn). Điều này có thể thực hiện được trong Firefox, nhưng không khả thi với iOS Safari, vì vậy nó không khả thi cho trường hợp sử dụng cụ thể của tôi.

Các trình duyệt, vui lòng ...

Không cần phải nói điều này thật nực cười. Thực tế là các trang web không được cung cấp thông báo rằng một phần tử giao diện người dùng quan trọng đã thay đổi chỉ đơn giản là buồn cười. Đây thực sự là một lỗi trong thông số kỹ thuật, vì nó không bao giờ được dành cho giao diện người dùng chụp đa phương tiện toàn màn hình và về mặt kỹ thuật , việc không kích hoạt sự kiện "thay đổi" .

Tuy nhiên , các nhà cung cấp trình duyệt có thể vui lòng nhận ra thực tế của điều này? Điều này có thể được giải quyết bằng sự kiện "hoàn thành" mới được kích hoạt ngay cả khi không có thay đổi nào xảy ra hoặc bạn có thể chỉ cần kích hoạt "thay đổi". Vâng, điều đó sẽ chống lại thông số kỹ thuật, nhưng đối với tôi, việc trích xuất một sự kiện thay đổi về phía JavaScript là điều tầm thường, nhưng về cơ bản là không thể tạo ra sự kiện "xong" của riêng tôi. Ngay cả giải pháp của tôi thực sự chỉ là phỏng đoán, nếu không có gì đảm bảo về trạng thái của trình duyệt.

Về cơ bản, API này về cơ bản không thể sử dụng được cho các thiết bị di động và tôi nghĩ rằng một thay đổi trình duyệt tương đối đơn giản có thể làm cho việc này dễ dàng hơn vô cùng đối với các nhà phát triển web * bước ra khỏi hộp xà phòng *.



7

Khi bạn chọn một tệp và nhấp vào mở / hủy, inputphần tử sẽ mất tiêu điểm hay còn gọi là blur. Giả sử giá trị ban đầu valuecủa inputgiá trị trống, bất kỳ giá trị không trống nào trong blurtrình xử lý của bạn sẽ cho biết OK và giá trị trống sẽ có nghĩa là Hủy.

CẬP NHẬT: Không blurđược kích hoạt khi inputẩn. Vì vậy, không thể sử dụng thủ thuật này với tải lên dựa trên IFRAME, trừ khi bạn muốn tạm thời hiển thị input.


3
Trong Firefox 10 beta và Chrome 16, tính năng blurnày không được kích hoạt khi bạn chọn một tệp. Chưa thử trong các trình duyệt khác.
Blaise

1
Điều đó không hoạt động - hiện tượng mờ trên đầu vào được kích hoạt ngay sau khi nhấp. Chrome 63.0.3239.84 x64 trên Win7.
Qwertiy

7
/* Tested on Google Chrome */
$("input[type=file]").bind("change", function() {
    var selected_file_name = $(this).val();
    if ( selected_file_name.length > 0 ) {
        /* Some file selected */
    }
    else {
        /* No file selected or cancel/close
           dialog button clicked */
        /* If user has select a file before,
           when they submit, it will treated as
           no file selected */
    }
});

6
Bạn đã kiểm tra xem elsetuyên bố của bạn có bao giờ được đánh giá không?
jayarjo

Theo như tôi nhớ khi tôi viết câu trả lời này, nếu người dùng chọn một tệp và sau đó chọn lại tệp (nhưng sau đó hủy bỏ), nó sẽ được coi là không có tệp nào được chọn, tôi chỉ sử dụng cảnh báo tại biến select_file_name để kiểm tra nó. Dù sao, đã không thử nghiệm nó nữa kể từ đó.
Rizky

4
Tôi có thể nói, sau một số thử nghiệm trình duyệt chéo, Firefox không kích hoạt sự kiện thay đổi khi hủy, cũng như không xóa các tệp hiện có đã chọn nếu được mở lại và hủy nhấp lần thứ hai. Lạ nhỉ?
mix3d

7

Hầu hết các giải pháp này không hiệu quả với tôi.

Vấn đề là bạn không bao giờ biết sự kiện nào sẽ được kích hoạt nắm đấm, có clickhay changekhông? Bạn không thể giả định bất kỳ thứ tự nào, vì nó có thể phụ thuộc vào việc triển khai của trình duyệt.

Ít nhất trong Opera và Chrome (cuối năm 2015) clickđược kích hoạt ngay trước khi 'lấp đầy' đầu vào bằng các tệp, vì vậy bạn sẽ không bao giờ biết khoảng thời gian files.length != 0cho đến khi bạn trì hoãn clickđể được kích hoạt sau đó change.

Đây là mã:

var inputfile = $("#yourid");

inputfile.on("change click", function(ev){
    if (ev.originalEvent != null){
        console.log("OK clicked");
    }
    document.body.onfocus = function(){
        document.body.onfocus = null;
        setTimeout(function(){
            if (inputfile.val().length === 0) console.log("Cancel clicked");
        }, 1000);
    };
});

Nếu bạn nhấp vào trang ... "Hủy đã nhấp" ... = | (Đã thử nghiệm với Chrome)
Eduardo Lucio

5

Chỉ cần lắng nghe sự kiện nhấp chuột là tốt.

Tiếp theo từ ví dụ của Shiboe, đây là một ví dụ về jQuery:

var godzilla = $('#godzilla');
var godzillaBtn = $('#godzilla-btn');

godzillaBtn.on('click', function(){
    godzilla.trigger('click');
});

godzilla.on('change click', function(){

    if (godzilla.val() != '') {
        $('#state').html('You have chosen a Mech!');    
    } else {
        $('#state').html('Choose your Mech!');
    }

});

Bạn có thể thấy nó hoạt động tại đây: http://jsfiddle.net/T3Vwz


1
Tôi đã thử nghiệm trên Chrome 51, nó không hoạt động vào lần đầu tiên bạn chọn tệp. Giải pháp là thêm thời gian trễ: jsfiddle.net/7jfbmunh
Benoit Blanchon

Fiddle của bạn không hoạt động với tôi - sử dụng Firefox 58.0.2
barrypicker

4

Bạn có thể bắt được thông báo hủy nếu bạn chọn cùng một tệp như trước đó và bạn nhấp vào hủy: trong trường hợp này.

Bạn có thể làm như thế này:

<input type="file" id="myinputfile"/>
<script>
document.getElementById('myinputfile').addEventListener('change', myMethod, false);
function myMethod(evt) {
  var files = evt.target.files; 
  f= files[0];
  if (f==undefined) {
     // the user has clicked on cancel
  }
  else if (f.name.match(".*\.jpg")|| f.name.match(".*\.png")) {
     //.... the user has choosen an image file
     var reader = new FileReader();
     reader.onload = function(evt) { 
        try {
        myimage.src=evt.target.result;
            ...
         } catch (err) {
            ...
         }
     };
  }     
  reader.readAsDataURL(f);          
</script>

1
Thnkx @loveJs bài đăng này thực sự giúp ích cho tôi.
VPK

4
Không chính xác, nếu người sử dụng chọn cùng một tập tin đó không phải là cancel = (
Tiago Peres França

13
onchange chỉ kích hoạt nếu có sự thay đổi. Vì vậy, nếu tệp là cùng tệp với trước đó, trình nghe onchange sẽ không kích hoạt.
Shane

1
Bạn có thể xóa lựa chọn đầu vào (input.value = '') sau khi bạn phát hiện thay đổi đầu tiên, do đó, thay đổi lần thứ hai sẽ kích hoạt ngay cả khi người dùng chọn lại cùng một tệp.
Chris

1
@CodeGems được phép đặt giá trị input.value theo chương trình thành một chuỗi trống. Nhưng bạn nói đúng rằng không được phép đặt nó thành bất kỳ giá trị nào khác.
Chris

4

Cách dễ nhất là kiểm tra xem có tệp nào trong bộ nhớ tạm thời hay không. Nếu bạn muốn nhận sự kiện thay đổi mỗi khi người dùng nhấp vào đầu vào tệp, bạn có thể kích hoạt sự kiện đó.

var yourFileInput = $("#yourFileInput");

yourFileInput.on('mouseup', function() {
    $(this).trigger("change");
}).on('change', function() {
    if (this.files.length) {
        //User chose a picture
    } else {
        //User clicked cancel
    }
});

2

Giải pháp của Shiboe sẽ là một giải pháp tốt nếu nó hoạt động trên webkit di động, nhưng nó không. Những gì tôi có thể nghĩ ra là thêm trình nghe sự kiện di chuột vào một số đối tượng dom tại thời điểm cửa sổ nhập tệp được mở, như sau:

 $('.upload-progress').mousemove(function() {
        checkForFiles(this);
      });
      checkForFiles = function(me) {
        var filefield = $('#myfileinput');
        var files = filefield.get(0).files;
        if (files == undefined || files[0] == undefined) $(me).remove(); // user cancelled the upload
      };

Sự kiện di chuyển chuột bị chặn khỏi trang trong khi hộp thoại tệp đang mở và khi hộp thoại đóng sẽ kiểm tra xem có tệp nào trong đầu vào tệp hay không. Trong trường hợp của tôi, tôi muốn một chỉ báo hoạt động chặn mọi thứ cho đến khi tệp được tải lên, vì vậy tôi chỉ muốn xóa chỉ báo của mình khi hủy.

Tuy nhiên, điều này không giải quyết được cho thiết bị di động, vì không có chuột để di chuyển. Giải pháp của tôi ở đó chưa hoàn hảo, nhưng tôi nghĩ nó đủ tốt.

       $('.upload-progress').bind('touchstart', function() {
        checkForFiles(this);
      });

Bây giờ chúng ta đang lắng nghe một cú chạm trên màn hình để kiểm tra các tệp tương tự. Tôi khá tin tưởng rằng ngón tay của người dùng sẽ được đưa lên màn hình khá nhanh sau khi hủy và loại bỏ chỉ báo hoạt động này.

Người ta cũng có thể chỉ thêm chỉ báo hoạt động trên sự kiện thay đổi đầu vào tệp, nhưng trên thiết bị di động thường có độ trễ vài giây giữa việc chọn hình ảnh và kích hoạt sự kiện thay đổi, vì vậy UX tốt hơn nhiều cho chỉ báo hoạt động được hiển thị tại bắt đầu của quá trình.


2

Tôi đã tìm thấy thuộc tính này, nó đơn giản nhất.

if ($('#selectedFile')[0].files.length > 1)
{
   // Clicked on 'open' with file
} else {
   // Clicked on 'cancel'
}

Đây, selectedFilelà một input type=file.


Đây là một giải pháp tốt đối với tôi, ngoại trừ việc nó nên> = 1
Bron Thulke

2

Tôi biết đây là một câu hỏi rất cũ nhưng để đề phòng nó giúp ích cho ai đó, tôi thấy khi sử dụng sự kiện onmousemove để phát hiện việc hủy, cần phải kiểm tra hai hoặc nhiều sự kiện như vậy trong một khoảng thời gian ngắn. Điều này là do các sự kiện onmousemove đơn lẻ được tạo bởi trình duyệt (Chrome 65) mỗi khi con trỏ được di chuyển ra khỏi cửa sổ hộp thoại tệp đã chọn và mỗi lần nó được di chuyển ra khỏi cửa sổ chính và quay lại. Một bộ đếm đơn giản của các sự kiện di chuyển chuột cùng với thời gian chờ trong thời gian ngắn để đặt lại bộ đếm về 0 đã có tác dụng.


1
Đoạn đầu tiên là một câu trả lời tốt, mặc dù nó có thể được chia thành nhiều đoạn để dễ đọc hơn. Nhưng hai dòng "SOAPBOX" đó khiến nó trở thành Không trả lời vì câu hỏi không thuộc câu trả lời. Bạn có thể viết lại / diễn đạt lại câu trả lời của mình một chút không? Cảm ơn bạn.
Filnor

1

Trong trường hợp của tôi, tôi đã phải ẩn nút gửi trong khi người dùng đang chọn hình ảnh.

Đây là những gì tôi nghĩ ra:

$(document).on('click', '#image-field', function(e) {
  $('.submit-button').prop('disabled', true)
})
$(document).on('focus', '#image-field'), function(e) {
  $('.submit-button').prop('disabled', false)
})

#image-fieldlà bộ chọn tệp của tôi. Khi ai đó nhấp vào nó, tôi vô hiệu hóa nút gửi biểu mẫu. Vấn đề là, khi hộp thoại tệp đóng - không quan trọng họ chọn tệp hay hủy - #image-fieldđã lấy lại tiêu điểm, vì vậy tôi lắng nghe sự kiện đó.

CẬP NHẬT

Tôi thấy rằng, điều này không hoạt động trong safari và poltergeist / phantomjs. Hãy tính đến thông tin này nếu bạn muốn triển khai nó.


1

Kết hợp các giải pháp của Shiboe và alx, tôi đã có mã đáng tin cậy nhất:

var selector = $('<input/>')
   .attr({ /* just for example, use your own attributes */
      "id": "FilesSelector",
      "name": "File",
      "type": "file",
      "contentEditable": "false" /* if you "click" on input via label, this prevents IE7-8 from just setting caret into file input's text filed*/
   })
   .on("click.filesSelector", function () {
      /* do some magic here, e.g. invoke callback for selection begin */
      var cancelled = false; /* need this because .one calls handler once for each event type */
      setTimeout(function () {
         $(document).one("mousemove.filesSelector focusin.filesSelector", function () {
            /* namespace is optional */
            if (selector.val().length === 0 && !cancelled) {
               cancelled = true; /* prevent double cancel */
               /* that's the point of cancel,   */
            }
         });                    
      }, 1); /* 1 is enough as we just need to delay until first available tick */
   })
   .on("change.filesSelector", function () {
      /* do some magic here, e.g. invoke callback for successful selection */
   })
   .appendTo(yourHolder).end(); /* just for example */

Nói chung, sự kiện di chuyển chuột thực hiện thủ thuật, nhưng trong trường hợp người dùng thực hiện một nhấp chuột và hơn:

  • đã hủy hộp thoại mở tệp bằng phím thoát (không di chuyển chuột), thực hiện một cú nhấp chuột chính xác khác để mở lại hộp thoại tệp ...
  • chuyển tiêu điểm sang bất kỳ ứng dụng nào khác, thay vì quay lại hộp thoại mở tệp của trình duyệt và đóng nó, hơn là mở lại bằng phím enter hoặc phím cách ...

... chúng tôi sẽ không nhận được sự kiện di chuyển chuột do đó không có lệnh gọi lại hủy. Hơn nữa, nếu người dùng hủy hộp thoại thứ hai và di chuyển chuột, chúng tôi sẽ nhận được 2 lệnh gọi lại hủy. May mắn thay, sự kiện jQuery focusIn đặc biệt sẽ xuất hiện trên tài liệu trong cả hai trường hợp, giúp chúng ta tránh những trường hợp như vậy. Hạn chế duy nhất là nếu một trong hai khóa sự kiện focusIn.


Tôi đã bắt gặp mousemovesự kiện documenttrong khi chọn tệp trong hộp thoại hệ điều hành trong Chrome 56.0.2924.87 trên Ubuntu 16.10. Không thành vấn đề, khi không di chuyển chuột hoặc chỉ sử dụng bàn phím để chọn tệp. Tôi đã phải thay thế mousemovebằng keydownđể phát hiện hủy càng sớm càng tốt, nhưng không "quá sớm", khi hộp thoại vẫn đang mở.
Ferdinand Prantl

1

Tôi thấy rằng phản hồi của tôi sẽ khá lỗi thời, nhưng không bao giờ ít hơn. Tôi phải đối mặt với cùng một vấn đề. Vì vậy, đây là giải pháp của tôi. Đoạn mã hữu ích nhất được cắt là mã của KGA. Nhưng nó không hoàn toàn hoạt động và hơi phức tạp. Nhưng tôi đã đơn giản hóa nó.

Ngoài ra, tác nhân gây ra rắc rối chính là thực tế, sự kiện 'thay đổi' đó không đến ngay lập tức sau khi tiêu điểm, vì vậy chúng ta phải đợi một thời gian.

"#appendfile" - người dùng nhấp vào để nối một tệp mới. Hrefs lấy các sự kiện tiêu điểm.

$("#appendfile").one("focusin", function () {
    // no matter - user uploaded file or canceled,
    // appendfile gets focus
    // change doesn't come instantly after focus, so we have to wait for some time
    // wrapper represents an element where a new file input is placed into
    setTimeout(function(){
        if (wrapper.find("input.fileinput").val() != "") {
            // user has uploaded some file
            // add your logic for new file here
        }
        else {
            // user canceled file upload
            // you have to remove a fileinput element from DOM
        }
    }, 900);
});

1

Bạn có thể phát hiện điều này chỉ trong một số trường hợp hạn chế. Cụ thể, trong chrome nếu một tệp được chọn trước đó và sau đó hộp thoại tệp được nhấp và hủy được nhấp vào, Chrome sẽ xóa tệp và kích hoạt sự kiện onChange.

https://code.google.com/p/chromium/issues/detail?id=2508

Trong trường hợp này, bạn có thể phát hiện điều này bằng cách xử lý sự kiện onChange và kiểm tra thuộc tính tệp .


1

Những điều sau đây dường như phù hợp với tôi (trên máy tính để bàn, cửa sổ):

var openFile = function (mimeType, fileExtension) {
    var defer = $q.defer();
    var uploadInput = document.createElement("input");
    uploadInput.type = 'file';
    uploadInput.accept = '.' + fileExtension + ',' + mimeType;

    var hasActivated = false;

    var hasChangedBeenCalled = false;
    var hasFocusBeenCalled = false;
    var focusCallback = function () {
        if (hasActivated) {
            hasFocusBeenCalled = true;
            document.removeEventListener('focus', focusCallback, true);
            setTimeout(function () {
                if (!hasChangedBeenCalled) {
                    uploadInput.removeEventListener('change', changedCallback, true);
                    defer.resolve(null);
                }
            }, 300);
        }
    };

    var changedCallback = function () {
        uploadInput.removeEventListener('change', changedCallback, true);
        if (!hasFocusBeenCalled) {
            document.removeEventListener('focus', focusCallback, true);
        }
        hasChangedBeenCalled = true;
        if (uploadInput.files.length === 1) {
            //File picked
            var reader = new FileReader();
            reader.onload = function (e) {
                defer.resolve(e.target.result);
            };
            reader.readAsText(uploadInput.files[0]);
        }
        else {
            defer.resolve(null);
        }
    };
    document.addEventListener('focus', focusCallback, true); //Detect cancel
    uploadInput.addEventListener('change', changedCallback, true); //Detect when a file is picked
    uploadInput.click();
    hasActivated = true;
    return defer.promise;
}

Điều này sử dụng anglejs $ q nhưng bạn có thể thay thế nó bằng bất kỳ khung hứa hẹn nào khác nếu cần.

Đã thử nghiệm trên IE11, Edge, Chrome, Firefox, nhưng dường như nó không hoạt động trên Chrome trên Máy tính bảng Android vì nó không kích hoạt sự kiện Focus.


1

Trường file-type, thật khó chịu, không phản hồi với nhiều sự kiện (mờ sẽ rất đáng yêu). Tôi thấy rất nhiều người đề xuất changecác giải pháp định hướng và họ bị phản đối.

changehoạt động, nhưng nó có một lỗ hổng lớn (so với những gì chúng tôi muốn xảy ra).

Khi bạn mới tải một trang chứa trường tệp, hãy mở hộp và nhấn hủy. Không có gì thay đổi .

Những gì tôi chọn làm là tải ở trạng thái kiểm soát.

  • Phần tiếp theo của biểu mẫu a section#after-imagetrong trường hợp của tôi bị ẩn khỏi chế độ xem. Khi tôi file fieldthay đổi, nút tải lên sẽ hiển thị. Sau khi tải lên thành công, section#after-imageđược hiển thị.
  • Nếu người dùng tải, mở hộp thoại-tệp, sau đó hủy bỏ, họ sẽ không bao giờ thấy nút tải lên.
  • Nếu người dùng chọn một tệp, nút tải lên sẽ hiển thị. Nếu sau đó họ mở hộp thoại và hủy bỏ,change sự kiện sẽ được kích hoạt bởi hành động hủy này và ở đó tôi có thể (và làm) ẩn lại nút tải lên của mình cho đến khi chọn được tệp thích hợp.

Tôi đã may mắn rằng trạng thái được kiểm soát này đã là thiết kế của biểu mẫu của tôi. Bạn không cần phải sử dụng cùng một kiểu, chỉ cần ẩn nút tải lên ban đầu và sau khi thay đổi, hãy đặt trường ẩn hoặc biến javascript thành thứ mà bạn có thể giám sát khi gửi.

Tôi đã thử thay đổi giá trị của tệp [0] trước khi trường được tương tác với. Điều này không làm bất cứ điều gì liên quan đến trao đổi.

Vì vậy, có, changehoạt động, ít nhất là tốt như chúng tôi sẽ nhận được. Trường tệp được bảo mật, vì những lý do rõ ràng, nhưng trước sự thất vọng của các nhà phát triển có thiện chí.

Nó không phù hợp với mục đích của tôi, nhưng bạn có thể onclicktải một lời nhắc cảnh báo (không phải alert()vì điều đó ngăn chặn quá trình xử lý trang) và ẩn nó nếu thay đổi được kích hoạt và tệp [0] là trống. Nếu thay đổi không được kích hoạt, div vẫn ở trạng thái của nó.


0

Có một cách hackish để làm điều này (thêm callbacks hoặc giải quyết một số triển khai hứa hẹn / trì hoãn thay vì alert()gọi):

var result = null;

$('<input type="file" />')
    .on('change', function () {
        result = this.files[0];
        alert('selected!');
    })
    .click();

setTimeout(function () {
    $(document).one('mousemove', function () {
        if (!result) {
            alert('cancelled');
        }
    });
}, 1000);

Cách hoạt động: trong khi hộp thoại chọn tệp đang mở, tài liệu không nhận được các sự kiện con trỏ chuột. Có độ trễ 1000ms để cho phép hộp thoại thực sự xuất hiện và chặn cửa sổ trình duyệt. Đã kiểm tra trong Chrome và Firefox (chỉ dành cho Windows).

Nhưng đây không phải là cách đáng tin cậy để phát hiện hộp thoại bị hủy. Tuy nhiên, có thể cải thiện một số hành vi giao diện người dùng cho bạn.


Một nhược điểm lớn là trên điện thoại và máy tính bảng, họ không sử dụng chuột bình thường!
Peter

0

Đây là giải pháp của tôi, sử dụng tiêu điểm đầu vào tệp (không sử dụng bất kỳ bộ hẹn giờ nào)

var fileInputSelectionInitiated = false;

function fileInputAnimationStart() {
    fileInputSelectionInitiated = true;
    if (!$("#image-selector-area-icon").hasClass("fa-spin"))
        $("#image-selector-area-icon").addClass("fa-spin");
    if (!$("#image-selector-button-icon").hasClass("fa-spin"))
        $("#image-selector-button-icon").addClass("fa-spin");
}

function fileInputAnimationStop() {
    fileInputSelectionInitiated = false;
    if ($("#image-selector-area-icon").hasClass("fa-spin"))
        $("#image-selector-area-icon").removeClass("fa-spin");
    if ($("#image-selector-button-icon").hasClass("fa-spin"))
        $("#image-selector-button-icon").removeClass("fa-spin");
}

$("#image-selector-area-wrapper").click(function (e) {
    $("#fileinput").focus();
    $("#fileinput").click();
});

$("#preview-image-wrapper").click(function (e) {
    $("#fileinput").focus();
    $("#fileinput").click();
});

$("#fileinput").click(function (e) {
    fileInputAnimationStart();
});

$("#fileinput").focus(function (e) {
    fileInputAnimationStop();
});

$("#fileinput").change(function(e) {
    // ...
}


Chạy đoạn mã của bạn mang lại cho tôiError: { "message": "Uncaught SyntaxError: missing ) after argument list", "filename": "https://stacksnippets.net/js", "lineno": 51, "colno": 1 }
Connexo

0

Điều này tốt nhất là hacky, nhưng đây là một ví dụ hoạt động về giải pháp của tôi để phát hiện xem người dùng đã tải lên tệp hay chưa và chỉ cho phép họ tiếp tục nếu họ đã tải tệp lên.

Về cơ bản ẩn Continue, Save, Proceedhoặc bất cứ nút bấm của bạn là. Sau đó, trong JavaScript, bạn lấy tên tệp. Nếu tên tệp không có giá trị, thì không hiển thịContinue nút. Nếu nó có một giá trị, thì hãy hiển thị nút. Điều này cũng hoạt động nếu lúc đầu họ tải lên một tệp và sau đó họ cố tải lên một tệp khác và nhấp vào hủy.

Đây là mã.

HTML:

<div class="container">
<div class="row">
    <input class="file-input" type="file" accept="image/*" name="fileUpload" id="fileUpload" capture="camera">
    <label for="fileUpload" id="file-upload-btn">Capture or Upload Photo</label>
</div>
<div class="row padding-top-two-em">
    <input class="btn btn-success hidden" id="accept-btn" type="submit" value="Accept & Continue"/>
    <button class="btn btn-danger">Back</button>
</div></div>

JavaScript:

$('#fileUpload').change(function () {
    var fileName = $('#fileUpload').val();
    if (fileName != "") {
        $('#file-upload-btn').html(fileName);
        $('#accept-btn').removeClass('hidden').addClass('show');
    } else {
        $('#file-upload-btn').html("Upload File");
        $('#accept-btn').addClass('hidden');
    }
});

CSS:

.file-input {
    width: 0.1px;
    height: 0.1px;
    opacity: 0;
    overflow: hidden;
    position: absolute;
    z-index: -1; 
}

.file-input + label {
    font-size: 1.25em;
    font-weight: normal;
    color: white;
    background-color: blue;
    display: inline-block;
    padding: 5px;
}

.file-input:focus + label,
.file-input + label:hover {
    background-color: red;
}

.file-input + label {
    cursor: pointer;
}

.file-input + label * {
    pointer-events: none;
}

Đối với CSS, phần lớn điều này là làm cho trang web và nút có thể truy cập được cho tất cả mọi người. Tạo kiểu cho nút của bạn theo bất kỳ thứ gì bạn thích.


0

Chà, điều này không trả lời chính xác câu hỏi của bạn. Giả định của tôi là, bạn có một tình huống, khi bạn thêm đầu vào tệp và gọi lựa chọn tệp, và nếu người dùng nhấn hủy, bạn chỉ cần xóa đầu vào.

Nếu đúng như vậy, thì: Tại sao phải thêm đầu vào tệp trống?

Tạo một cái ngay lập tức, nhưng chỉ thêm nó vào DOM khi nó được điền vào. Như vậy:

    var fileInput = $("<input type='file' name='files' style='display: none' />");
    fileInput.bind("change", function() {
        if (fileInput.val() !== null) {
            // if has value add it to DOM
            $("#files").append(fileInput);
        }
    }).click();

Vì vậy, ở đây tôi tạo <input type = "file" /> ngay lập tức, liên kết với sự kiện thay đổi của nó và sau đó ngay lập tức gọi nhấp chuột. Thay đổi sẽ chỉ kích hoạt khi người dùng chọn một tệp và nhấn Ok, nếu không, đầu vào sẽ không được thêm vào DOM, do đó sẽ không được gửi.

Ví dụ làm việc tại đây: https://jsfiddle.net/69g0Lxno/3/


0

// Sử dụng di chuột thay vì làm mờ

var fileInput = $("#fileInput");

if (fileInput.is(":hover") { 

    //open
} else {

}

0

Nếu bạn đã yêu cầu JQuery, giải pháp này có thể thực hiện công việc (đây là mã chính xác mà tôi thực sự cần trong trường hợp của mình, mặc dù việc sử dụng Promise chỉ để buộc mã đợi cho đến khi lựa chọn tệp được giải quyết):

await new Promise(resolve => {
    const input = $("<input type='file'/>");
    input.on('change', function() {
        resolve($(this).val());
    });
    $('body').one('focus', '*', e => {
        resolve(null);
        e.stopPropagation();
    });
    input.click();

});


0

Có một số giải pháp được đề xuất trong chủ đề này và khó phát hiện khi người dùng nhấp vào nút "Hủy" trên hộp chọn tệp là một vấn đề ảnh hưởng đến nhiều người.

Thực tế là không có cách nào đáng tin cậy 100% để phát hiện xem người dùng có nhấp vào nút "Hủy" trên hộp chọn tệp hay không. Nhưng có những cách để phát hiện một cách đáng tin cậy nếu người dùng đã thêm tệp vào tệp đầu vào. Vì vậy, đây là chiến lược cơ bản của câu trả lời này!

Tôi quyết định thêm câu trả lời này vì rõ ràng các câu trả lời khác không hoạt động trên hầu hết các trình duyệt hoặc được đảm bảo trên thiết bị di động.

Tóm lại, mã dựa trên 3 điểm:

  1. Tệp đầu vào ban đầu được tạo động trong "bộ nhớ" trong js (chúng tôi không thêm nó vào "HTML" tại thời điểm này);
  2. Sau khi thêm tệp thì tệp đầu vào sẽ được thêm vào HTML, nếu không thì không có gì xảy ra;
  3. Việc xóa tệp được thực hiện bằng cách xóa tệp đầu vào khỏi HTML bởi một sự kiện cụ thể, có nghĩa là việc "chỉnh sửa" / "sửa đổi" tệp được thực hiện bằng cách xóa tệp đầu vào cũ và tạo một tệp mới.

Để hiểu rõ hơn, hãy xem đoạn mã bên dưới và các ghi chú.

[...]
<button type="button" onclick="addIptFl();">ADD INPUT FILE!</button>
<span id="ipt_fl_parent"></span>
[...]
function dynIptFl(jqElInst, funcsObj) {
    if (typeof funcsObj === "undefined" || funcsObj === "") {
        funcsObj = {};
    }
    if (funcsObj.hasOwnProperty("before")) {
        if (!funcsObj["before"].hasOwnProperty("args")) {
            funcsObj["before"]["args"] = [];
        }
        funcsObj["before"]["func"].apply(this, funcsObj["before"]["args"]);
    }
    var jqElInstFl = jqElInst.find("input[type=file]");

    // NOTE: Open the file selection box via js. By Questor
    jqElInstFl.trigger("click");

    // NOTE: This event is triggered if the user selects a file. By Questor
    jqElInstFl.on("change", {funcsObj: funcsObj}, function(e) {

        // NOTE: With the strategy below we avoid problems with other unwanted events
        // that may be associated with the DOM element. By Questor
        e.preventDefault();

        var funcsObj = e.data.funcsObj;
        if (funcsObj.hasOwnProperty("after")) {
            if (!funcsObj["after"].hasOwnProperty("args")) {
                funcsObj["after"]["args"] = [];
            }
            funcsObj["after"]["func"].apply(this, funcsObj["after"]["args"]);
        }
    });

}

function remIptFl() {

    // NOTE: Remove the input file. By Questor
    $("#ipt_fl_parent").empty();

}

function addIptFl() {

    function addBefore(someArgs0, someArgs1) {
    // NOTE: All the logic here happens just before the file selection box opens.
    // By Questor

        // SOME CODE HERE!

    }

    function addAfter(someArgs0, someArgs1) {
    // NOTE: All the logic here happens only if the user adds a file. By Questor

        // SOME CODE HERE!

        $("#ipt_fl_parent").prepend(jqElInst);

    }

    // NOTE: The input file is hidden as all manipulation must be done via js.
    // By Questor
    var jqElInst = $('\
<span>\
    <button type="button" onclick="remIptFl();">REMOVE INPUT FILE!</button>\
    <input type="file" name="input_fl_nm" style="display: block;">\
</span>\
');

    var funcsObj = {
        before: {
            func: addBefore,
            args: [someArgs0, someArgs1]
        },
        after: {
            func: addAfter,

            // NOTE: The instance with the input file ("jqElInst") could be passed
            // here instead of using the context of the "addIptFl()" function. That
            // way "addBefore()" and "addAfter()" will not need to be inside "addIptFl()",
            // for example. By Questor
            args: [someArgs0, someArgs1]

        }
    };
    dynIptFl(jqElInst, funcsObj);

}

Cảm ơn! = D


0

Chúng tôi đã đạt được ở góc độ như dưới đây.

    1. liên kết sự kiện nhấp chuột trên tệp loại đầu vào.
      1. Đính kèm sự kiện tiêu điểm với cửa sổ và thêm điều kiện nếu uploadPanel là true thì hiển thị bảng điều khiển.
      2. khi nhấp vào tệp loại đầu vào, giá trị boolean uploadPanel là true. và hộp thoại xuất hiện.
      3. khi hủy hoặc nhấp vào nút Esc thì hộp thoại và bảng điều khiển xuất hiện.

HTML

 <input type="file" formControlName="FileUpload" click)="handleFileInput($event.target.files)" />
          />

TS

this.uploadPanel = false;
handleFileInput(files: FileList) {
    this.fileToUpload = files.item(0);
    console.log("ggg" + files);
    this.uploadPanel = true;
  }



@HostListener("window:focus", ["$event"])
  onFocus(event: FocusEvent): void {
    if (this.uploadPanel == true) {
        console.log("cancel clicked")
        this.addSlot
        .get("FileUpload")
        .setValidators([
          Validators.required,
          FileValidator.validate,
          requiredFileType("png")
        ]);
      this.addSlot.get("FileUpload").updateValueAndValidity();
    }
  }

0

Chỉ cần thêm trình nghe 'thay đổi' vào đầu vào của bạn có loại là tệp. I E

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

Tôi đã sử dụng jQuery và rõ ràng là bất kỳ ai cũng có thể sử dụng valina JS (theo yêu cầu).

$("#file_to_upload").change(function() {

            if (this.files.length) {

            alert('file choosen');

            } else {

            alert('file NOT choosen');

            }

    });

.change()không được gọi một cách đáng tin cậy nếu người dùng nhấp vào "hủy" trên bộ chọn tệp.
Ben Wheeler

@benWheeler, tôi đã kiểm tra nó trên cả chrome và firefox và nó hoạt động của tôi nhưng không được thử nghiệm trên các trình duyệt khác.
Naveed Ali

0
    enter code here
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello</h1>
    <div id="cancel01">
      <button>Cancel</button>
    </div>

    <div id="cancel02">
      <button>Cancel</button>
    </div>

    <div id="cancel03">
      <button>Cancel</button>
    </div>

    <form>
      <input type="file" name="name" placeholder="Name" />
    </form>

    <script>
      const nameInput = document.querySelector('input[type="file"]');

      /******
       *The below code if for How to detect when cancel is clicked on file input
       ******/
      nameInput.addEventListener('keydown', e => {
        /******
         *If the cancel button is clicked,then you should change the input file value to empty
         ******/

        if (e.key == 'Backspace' || e.code == 'Backspace' || e.keyCode == 8) {
          console.log(e);

          /******
           *The below code will delete the file path
           ******/
          nameInput.value = '';
        }
      });
    </script>
  </body>
</html>

Các câu trả lời chỉ có mã được coi là chất lượng thấp: hãy đảm bảo cung cấp lời giải thích mã của bạn hoạt động như thế nào và cách nó giải quyết vấn đề. Nó sẽ giúp ích cho cả người hỏi và người đọc trong tương lai nếu bạn có thể bổ sung thêm thông tin trong bài đăng của mình. Xem Giải thích các câu trả lời hoàn toàn dựa trên mã
Calos

0

Giải pháp lựa chọn tệp với đầu vào ẩn

Lưu ý: mã này không phát hiện ra việc hủy, nó cung cấp một cách để tránh sự cần thiết phải phát hiện trong trường hợp phổ biến mà mọi người cố gắng phát hiện ra nó.

Tôi đến đây khi đang tìm giải pháp cho việc tải tệp lên bằng đầu vào ẩn, tôi tin rằng đây là lý do phổ biến nhất để tìm cách phát hiện việc hủy đầu vào tệp (hộp thoại mở tệp -> nếu tệp đã được chọn thì hãy chạy một số mã, nếu không thì không làm gì cả), đây là giải pháp của tôi:

var fileSelectorResolve;
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');

fileSelector.addEventListener('input', function(){
   fileSelectorResolve(this.files[0]);
   fileSelectorResolve = null;
   fileSelector.value = '';
});

function selectFile(){
   if(fileSelectorResolve){
      fileSelectorResolve();
      fileSelectorResolve = null;
   }
   return new Promise(function(resolve){
      fileSelectorResolve = resolve;
      fileSelector.dispatchEvent(new MouseEvent('click'));
   });
}

Ví dụ sử dụng:

Lưu ý rằng nếu không có tệp nào được chọn thì dòng đầu tiên sẽ chỉ trả về một lần nữa khi selectFile()được gọi lại (hoặc nếu bạn đã gọi fileSelectorResolve()từ nơi khác).

async function logFileName(){
   const file = await selectFile();
   if(!file) return;
   console.log(file.name);
}

Một vi dụ khac:

async function uploadFile(){
   const file = await selectFile();
   if(!file) return;

   // ... make an ajax call here to upload the file ...
}

Trong chrome 83.0, tôi không nhận được lệnh gọi lại nào cho sự kiện đầu vào khi người dùng hủy và cũng không phải trong lần thử thứ 2
Soylent Graham

1
@SoylentGraham Có, bởi vì mã này không phát hiện việc hủy, nó cung cấp một cách để tránh sự cần thiết phải phát hiện nó trong một trường hợp phổ biến mà mọi người cố gắng phát hiện ra nó. Vì tôi không rõ về điều đó, tôi sẽ thêm nhận xét này vào câu trả lời của mình.
khoai tây

Tôi nghĩ thật tệ, tôi đã đọc nhầm câu trả lời của bạn là "nó cho bạn biết người dùng đã hủy vào lần thử thứ hai"
Soylent Graham vào

-1

Bạn có thể tạo trình nghe thay đổi jquery trên trường đầu vào và phát hiện người dùng đó hủy hoặc đóng cửa sổ tải lên theo giá trị của trường.

đây là một ví dụ:

//when upload button change
$('#upload_btn').change(function(){
    //get uploaded file
    var file = this.files[0];

    //if user choosed a file
    if(file){
        //upload file or perform your desired functiuonality
    }else{
        //user click cancel or close the upload window
    }
});

Không biết tại sao điều này lại bị từ chối - đây là những gì tôi đang tìm kiếm. Cảm ơn bạn! 🙂
dùng1274820
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.