Sự kiện lựa chọn tệp đầu vào HTML không kích hoạt khi chọn cùng một tệp


204

Có bất kỳ cơ hội nào để phát hiện mọi lựa chọn tệp mà người dùng đã tạo cho HTML không input loại filephần tử không?

Điều này đã được hỏi nhiều lần trước đây, nhưng onchangesự kiện thường được đề xuất sẽ không kích hoạt nếu người dùng chọn lại cùng một tệp.


7
Mã của bạn sau đó cũng sẽ phải kích hoạt nếu người dùng nhấn Hủy sau đó? Người ta kỳ vọng rằng việc nhấn Hủy sẽ không làm được gì và tôi nghĩ rằng hầu hết người dùng sẽ mong đợi rằng việc chọn lại cùng một tệp sẽ có tác dụng tương tự như Hủy. Tôi không biết điều này có thể hay không nhưng tôi khuyên bạn nên xem xét lại thiết kế này.
KRyan

1
Khi hủy nó không nên bắn hoặc làm cho nó có thể được phát hiện. Điều này có nghĩa hơn là loại bỏ giao diện người dùng: Nếu một số hành động được gọi sau khi tệp được chọn, người dùng thường mong đợi hành động đó lặp lại nếu anh ta chọn lại tệp.
dronus

Có lẽ chúng ta có thể có hành vi này nếu chúng ta đặt inputgiá trị s thành '' sau khi thực hiện một thao tác nào đó với tệp. Nhưng điều đó cũng sẽ loại bỏ tên tập tin có thể nhìn thấy. Tuy nhiên, điều đó có thể ổn, vì tập tin thực sự được xử lý và kết quả của hành động đó có thể xuất hiện ở một nơi khác.
dronus

Plz Giải thích về Que Bạn muốn làm gì?
Champ

1
Tất cả những gì tôi muốn là mô phỏng các ứng dụng máy tính để bàn cũ. Nếu tôi 'mở' lại cùng một tệp trong ứng dụng máy tính để bàn, nó thường được tải lại hoặc nếu một số hành động được thực hiện với tệp (ví dụ như chuyển đổi nó thành định dạng khác) thì hành động này được thực hiện lại. Đây cũng là những gì người dùng máy tính để bàn có thể mong đợi từ một ứng dụng web, nhưng sự kiện fileđầu vào onchangekhông giống.
dronus

Câu trả lời:


278

Thiết lập giá trị của inputđể nulltrên mỗi onclicksự kiện. Điều này sẽ đặt lại inputgiá trị của và kích hoạt onchangesự kiện ngay cả khi cùng một đường dẫn được chọn.

input.onclick = function () {
    this.value = null;
};

input.onchange = function () {
    alert(this.value);
};​

Đây là một DEMO .

Lưu ý: Điều đó là bình thường nếu tệp của bạn có tiền tố là 'C: \ fakepath \'. Đó là một tính năng bảo mật ngăn JavaScript biết đường dẫn tuyệt đối của tệp. Trình duyệt vẫn biết nó trong nội bộ.


1
Tôi đã thử bản demo, nhưng (sử dụng Chrome 21) Tôi tiếp tục nhận được `C: \ fakepath` + sau đó là tên tệp tôi đã chọn (không bao gồm đường dẫn). Cảnh báo được hiển thị trên mỗi lựa chọn của cùng một tập tin mặc dù.
Jasper de Vries

1
@JasperdeVries Đó là một tính năng bảo mật ngăn JavaScript biết đường dẫn tuyệt đối của tệp. Trình duyệt vẫn biết đường dẫn nội bộ.
Brian Ustas

1
Bên cạnh đó, null là giá trị được phép duy nhất cho <input type = "file">. Vì vậy, nếu bạn đang cố gắng đặt nó thành không xác định và nhận được một ngoại lệ thì đó là lý do tại sao.
Noel Abrahams

5
Nó không hoạt động tốt trong IE11 trừ khi bạn thực hiện một thay đổi nhỏ: bản demo .

21
Tốt hơn hết là đặt this.value = nullở cuối phần onchangevì có thể kích hoạt phần tử đầu vào mà không cần nhấp vào nó (bằng cách sử dụng bàn phím). Bạn có thể lưu trữ input.filesnếu bạn cần tham khảo nó sau.
Halcyon

24
<form enctype='multipart/form-data'>
    <input onchange="alert(this.value); this.value=null; return false;" type='file'>
    <br>
    <input type='submit' value='Upload'>
</form>

this.value=null; chỉ cần thiết cho Chrome, Firefox sẽ hoạt động tốt chỉ với return false;

Đây là một FIDDLE


2
đơn giản và hiệu quả chỉ cần thử nghiệm trên IE và chrome mới nhất và hoạt động như một nét quyến rũ. Cảm ơn đã chia sẻ nó
Atul Chaudhary

8

Trong bài viết này, dưới tiêu đề "Sử dụng biểu mẫu nhập để chọn"

http://www.html5rocks.com/en/tutorials/file/dndfiles/

<input type="file" id="files" name="files[]" multiple />

<script>
function handleFileSelect(evt) {

    var files = evt.target.files; // FileList object

    // files is a FileList of File objects. List some properties.
    var output = [];
    for (var i = 0, f; f = files[i]; i++) {
     // Code to execute for every file selected
    }
    // Code to execute after that

}

document.getElementById('files').addEventListener('change', 
                                                  handleFileSelect, 
                                                  false);
</script>

Nó thêm trình lắng nghe sự kiện vào 'thay đổi', nhưng tôi đã kiểm tra nó và nó kích hoạt ngay cả khi bạn chọn cùng một tệp chứ không phải nếu bạn hủy.


Xem xét ý nghĩa mơ hồ của "thay đổi" trong trường hợp này, bạn đã thử điều này trong nhiều trình duyệt chưa? Bạn có thể muốn chỉ định những cái nào bạn đã thử trên web, các trình duyệt không hoàn toàn đồng thuận về những điều này.
Thor84no

2
Môi trường bạn sử dụng cho bài kiểm tra của bạn là gì? Trải nghiệm của tôi với Chrome là điều tôi đã nêu trong câu hỏi, changesự kiện sẽ chỉ phát sinh khi thay đổi tên tệp.
dronus

7

Sử dụng sự kiện onClick để xóa giá trị của mục tiêu đầu vào, mỗi lần người dùng nhấp vào trường. Điều này đảm bảo rằng sự kiện onChange cũng sẽ được kích hoạt cho cùng một tệp. Đã làm cho tôi :)

onInputClick = (event) => {
    event.target.value = ''
}

<input type="file" onChange={onFileChanged} onClick={onInputClick} />

Sử dụng TypeScript

onInputClick = ( event: React.MouseEvent<HTMLInputElement, MouseEvent>) => {
    const element = event.target as HTMLInputElement
    element.value = ''
}

Cảm ơn giải pháp.
Deepak Tek Touchani

1

Làm bất cứ điều gì bạn muốn làm sau khi tải tệp thành công. Chỉ sau khi hoàn thành quá trình xử lý tệp của bạn, đặt giá trị của điều khiển tệp thành chuỗi trống. Vì vậy, .change () sẽ luôn được gọi ngay cả khi tên tệp thay đổi hay không. ví dụ như bạn có thể làm điều này và làm việc cho tôi như sự quyến rũ

   $('#myFile').change(function () {
       LoadFile("myFile");//function to do processing of file.
       $('#myFile').val('');// set the value to empty of myfile control.
    });

1
handleChange({target}) {
    const files = target.files
    target.value = ''
}

1
Này ngCụ! Câu trả lời chỉ có mã có thể giải quyết vấn đề nhưng chúng hữu ích hơn nhiều nếu bạn giải thích cách họ giải quyết nó. Cộng đồng đòi hỏi lý thuyết cũng như mã cả để hiểu đầy đủ câu trả lời của bạn.
RBT

Mặc dù mã này có thể giải quyết câu hỏi, bao gồm giải thích về cách thức và lý do giải quyết vấn đề này thực sự sẽ giúp cải thiện chất lượng bài đăng của bạn và có thể dẫn đến nhiều lượt bình chọn hơn. Hãy nhớ rằng bạn đang trả lời câu hỏi cho độc giả trong tương lai, không chỉ người hỏi bây giờ. Vui lòng chỉnh sửa câu trả lời của bạn để thêm giải thích và đưa ra dấu hiệu về những hạn chế và giả định được áp dụng. Từ đánh giá
tiếng bíp đôi

1

Xóa giá trị của chỉ số 0 của đầu vào làm việc cho tôi . Vui lòng thử mã dưới đây, hy vọng nó sẽ hoạt động (AngularJs).

          scope.onClick = function() {
            input[0].value = "";
                input.click();
            };
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.