Làm cách nào để phát hiện kiểu đầu vào = tập tin Thay đổi tập tin cho cùng một tập tin?


131

Tôi muốn kích hoạt một sự kiện khi người dùng chọn một tập tin. Làm như vậy với .changesự kiện nó hoạt động nếu người dùng thay đổi tệp mỗi lần.

Nhưng tôi muốn kích hoạt sự kiện nếu người dùng chọn lại cùng một tệp.

  1. Người dùng chọn tập tin A.jpg(sự kiện cháy)
  2. Người dùng chọn tập tin B.jpg(sự kiện cháy)
  3. Người dùng chọn tệp B.jpg(sự kiện không kích hoạt, tôi muốn nó kích hoạt)

Tôi làm nó như thế nào?

Câu trả lời:


78

Bạn có thể lừa nó. Xóa phần tử tệp và thêm nó vào cùng một vị trí trong changesự kiện. Nó sẽ xóa đường dẫn tệp làm cho nó thay đổi mỗi lần.

Ví dụ trên jsFiddle.

Hoặc bạn có thể chỉ cần sử dụng .prop("value", ""), xem ví dụ này trên jsFiddle .

  • jQuery 1.6+ prop
  • Các phiên bản trước attr

@Pekka: Không chính xác. Nhưng anh ta chỉ có thể thích nghi với nó. Hãy nói rằng anh ta cần phải đăng các tập tin. Sau bài đăng, anh ta có thể gọi một hàm js sẽ loại bỏ và thêm bộ chọn tệp mới. Nó là có thể làm được.
BrunoLM

3
lưu ý rằng khi bạn sử dụng .attr("value", "")hoặc .val("")(như được đề xuất bởi @ wagner-leonardi bên dưới), nhà thám hiểm internet sẽ kích hoạt sự kiện thay đổi trong khi chrome không
fadomire

4
vì "value" là một thuộc tính và không phải là một thuộc tính của đầu vào, nên việc sử dụng jQuery được đề xuất sẽ là.prop("value", "")
Roger Barreto

70

Nếu bạn đã thử .attr("value", "")và không làm việc, đừng hoảng sợ (như tôi đã làm)

chỉ cần làm .val("")thay thế, và sẽ làm việc tốt


49

Bạn chỉ có thể đặt thành null đường dẫn tệp mỗi khi người dùng nhấp vào điều khiển. Bây giờ, ngay cả khi người dùng chọn cùng một tệp, sự kiện onchange sẽ được kích hoạt.

<input id="file" onchange="file_changed(this)" onclick="this.value=null;" type="file" accept="*/*" />

2
Tôi cần một giải pháp như thế này. Nó thực sự ngắn và hoàn thành công việc. Suy nghĩ tốt đẹp Mariusz Wiazowski.
Jay Dharmendra Solanki

Giải pháp khác là thay đổi giá trị khi thẻ đầu vào thay đổi. Nhưng chúng tôi không mong đợi giá trị được thay đổi sau khi chọn một tệp.
hát

1
Thật tuyệt, cách tốt hơn là loại bỏ và thêm phần tử vào dom một lần nữa, thx
David Dal Busco

24

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 = ''
}

17

Tôi đã làm điều này để làm việc bằng cách xóa giá trị nhập tệp trên Click và sau đó đăng tệp lên Thay đổi. Điều này cho phép người dùng chọn cùng một tệp hai lần liên tiếp và vẫn có sự kiện thay đổi để đăng lên máy chủ. Ví dụ của tôi sử dụng plugin biểu mẫu jQuery .

$('input[type=file]').click(function(){
    $(this).attr("value", "");
})  
$('input[type=file]').change(function(){
    $('#my-form').ajaxSubmit(options);      
})

onClickcháy trước đây onChange, vì vậy phương pháp này làm việc tuyệt vời cho tôi.
iplus26

8

Công việc này đối với tôi

<input type="file" onchange="function();this.value=null;return false;">

1
tôi đoán bạn có nghĩa là một cái gì đó như hàm () {this.value = null; trả lại sai; }
Jacek Pietal

7

Giải pháp VueJs

<input
                type="file"
                style="display: none;"
                ref="fileInput"
                accept="*"
                @change="onFilePicked"
                @click="$refs.fileInput.value=null"
>

1
Cảm ơn bạn đã trả lời biến thể này
Coisox

5

Lấy cảm hứng từ @braitsch Tôi đã sử dụng những điều sau đây trong AngularJS2 của tôi input-file-component

<input id="file" onclick="onClick($event) onchange="onChange($event)" type="file" accept="*/*" />

export class InputFile {

    @Input()
    file:File|Blob;

    @Output()
    fileChange = new EventEmitter();

    onClick(event) {
        event.target.value=''
    }
    onChange(e){
        let files  = e.target.files;
        if(files.length){
            this.file = files[0];
        }
        else { this.file = null}
        this.fileChange.emit(this.file);
    }
}

Ở đây onClick(event)đã giải cứu tôi :-)


3

Có lẽ điều dễ nhất bạn có thể làm là đặt giá trị thành một chuỗi trống. Điều này buộc nó phải 'thay đổi' tệp mỗi lần ngay cả khi cùng một tệp được chọn lại.

<input type="file" value="" />


3

Đây là giải pháp React-y tôi đã tìm thấy có hiệu quả với tôi:

onClick={event => event.target.value = null}


2

Nếu bạn không muốn sử dụng jQuery

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

Nó hoạt động tốt trong Firefox, nhưng đối với Chrome, bạn cần thêm this.value=null;sau khi cảnh báo.


2

Theo mặc định, thuộc tính giá trị của phần tử đầu vào bị xóa sau khi chọn tệp nếu đầu vào có nhiều thuộc tính. Nếu bạn không xóa thuộc tính này thì sự kiện "thay đổi" sẽ không được kích hoạt nếu bạn chọn cùng một tệp. Bạn có thể quản lý hành vi này bằng cách sử dụng multiplethuộc tính.

<!-- will be cleared -->
<input type="file" onchange="yourFunction()" multiple/>
<!-- won't be cleared -->
<input type="file" onchange="yourFunction()"/>

Tài liệu tham khảo


1

Bạn không thể tạo ra changelửa ở đây (hành vi chính xác, vì không có gì thay đổi). Tuy nhiên, bạn cũng có thể liên kết click... mặc dù điều này có thể bắn quá thường xuyên ... mặc dù không có nhiều trung gian giữa hai người.

$("#fileID").bind("click change", function() {
  //do stuff
});

Có vẻ như bạn chỉ đang lặp lại lời nói của anh ấy và .click()không "chọn lại".
BrunoLM

@BrunoLM - Không, không phải ... nhưng tôi nghĩ rằng bạn đã đọc qua phần mà tôi nói bạn không thể làm điều này, clicknó gần giống như nó được.
Nick Craver

1

Tạo cho đầu vào một sự kiện nhấp chuột và một sự kiện thay đổi. Sự kiện nhấp chuột làm trống đầu vào và sự kiện thay đổi chứa mã bạn muốn thực thi.

Vì vậy, sự kiện nhấp sẽ trống khi bạn nhấp vào nút nhập (trước khi cửa sổ tệp chọn mở ra), do đó, sự kiện thay đổi sẽ luôn kích hoạt khi bạn chọn tệp.

$("#input").click(function() {
  $("#input").val("")
});

$("#input").change(function() {
  //Your code you want to execute!
});
<input id="input" type="file">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>


0

Bạn có thể sử dụng form.reset()để xóa filesdanh sách đầu vào của tập tin . Điều này sẽ đặt lại tất cả các trường về giá trị mặc định, nhưng trong nhiều trường hợp, bạn có thể chỉ sử dụng kiểu nhập = 'tệp' trong một biểu mẫu để tải tệp lên. Trong giải pháp này, không cần phải sao chép phần tử và nối lại các sự kiện.

Cảm ơn philiplhmann


0

Tôi gặp vấn đề tương tự, tôi thông qua các giải pháp của anh ta ở trên nhưng họ không nhận được bất kỳ lời giải thích tốt nào về những gì đang thực sự xảy ra.

Giải pháp này tôi đã viết https://jsfiddle.net/r2wjp6u8/ không thực hiện nhiều thay đổi trong cây DOM, nó chỉ thay đổi giá trị của trường đầu vào. Từ khía cạnh hiệu suất, nó sẽ tốt hơn một chút.

Liên kết đến fiddle: https://jsfiddle.net/r2wjp6u8/

<button id="btnSelectFile">Upload</button>

<!-- Not displaying the Inputfield because the design changes on each browser -->
<input type="file" id="fileInput" style="display: none;">
<p>
  Current File: <span id="currentFile"></span>
</p>
<hr>
<div class="log"></div>


<script>
// Get Logging Element
var log = document.querySelector('.log');

// Load the file input element.
var inputElement = document.getElementById('fileInput');
inputElement.addEventListener('change', currentFile);

// Add Click behavior to button
document.getElementById('btnSelectFile').addEventListener('click', selectFile);

function selectFile() {
  if (inputElement.files[0]) {
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    // Reset the Input Field
    log.innerHTML += '<p>Removing file: ' + inputElement.files[0].name + '</p>'
    inputElement.value = '';
    // Check how manyf iles are selected and display filename
    log.innerHTML += '<p>Total files: ' + inputElement.files.length + '</p>'
    log.innerHTML += '<hr>'
  }

  // Once we have a clean slide, open fiel select dialog.
  inputElement.click();
};

function currentFile() {
    // If Input Element has a file
  if (inputElement.files[0]) {
    document.getElementById('currentFile').innerHTML = inputElement.files[0].name;
  }
}

</scrip>

0

Vì vậy, không có cách nào để chắc chắn 100% họ đang chọn cùng một tệp trừ khi bạn lưu trữ từng tệp và so sánh chúng theo chương trình.

Cách bạn tương tác với các tập tin (những gì JS không khi người dùng 'cập nhật' một tập tin) là HTML5 file APIJS FileReader .

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

https://scotch.io/tutorials/use-the-html5-file-api-to-work-with-files-locally-in-the-browser

Các hướng dẫn này chỉ cho bạn cách chụp và đọc siêu dữ liệu (được lưu dưới dạng đối tượng js) khi tệp được tải lên.

Tạo một hàm kích hoạt 'onChange' sẽ đọc-> store-> so sánh siêu dữ liệu của tệp hiện tại với các tệp trước đó. Sau đó, bạn có thể kích hoạt sự kiện của mình khi tệp mong muốn được chọn.


0

Hãy tin tôi, nó chắc chắn sẽ giúp bạn!

// there I have called two `onchange event functions` due to some different scenario processing.

<input type="file" class="selectImagesHandlerDialog" 
    name="selectImagesHandlerDialog" 
    onclick="this.value=null;" accept="image/x-png,image/gif,image/jpeg" multiple 
    onchange="delegateMultipleFilesSelectionAndOpen(event); disposeMultipleFilesSelections(this);" />


// delegating multiple files select and open
var delegateMultipleFilesSelectionAndOpen = function (evt) {

  if (!evt.target.files) return;

  var selectedPhotos = evt.target.files;
  // some continuous source

};


// explicitly removing file input value memory cache
var disposeMultipleFilesSelections = function () {
  this.val = null;
};

Hy vọng điều này sẽ giúp nhiều bạn.

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.