จะตรวจจับประเภทอินพุต = ไฟล์“ เปลี่ยนแปลง” สำหรับไฟล์เดียวกันได้อย่างไร?


133

ฉันต้องการเริ่มต้นเหตุการณ์เมื่อผู้ใช้เลือกไฟล์ การดำเนินการดัง.changeกล่าวจะได้ผลหากผู้ใช้เปลี่ยนไฟล์ทุกครั้ง

แต่ฉันต้องการเริ่มต้นเหตุการณ์หากผู้ใช้เลือกไฟล์เดิมอีกครั้ง

  1. ผู้ใช้เลือกไฟล์A.jpg(เหตุการณ์ไฟไหม้)
  2. ผู้ใช้เลือกไฟล์B.jpg(เหตุการณ์ไฟไหม้)
  3. ผู้ใช้เลือกไฟล์B.jpg(เหตุการณ์ไม่เริ่มทำงานฉันต้องการให้มันเริ่มทำงาน)

ฉันจะทำมันได้อย่างไร?

คำตอบ:


79

คุณสามารถหลอกล่อได้ ลบองค์ประกอบของไฟล์และเพิ่มในที่เดียวกันในchangeเหตุการณ์ มันจะลบเส้นทางของไฟล์ทำให้เปลี่ยนแปลงได้ทุกครั้ง

ตัวอย่างบน jsFiddle

หรือคุณสามารถใช้.prop("value", "")ดูตัวอย่างนี้บน jsFiddle

  • jQuery 1.6+ prop
  • เวอร์ชันก่อนหน้า attr

@Pekka: ไม่เป๊ะ แต่เขาสามารถปรับตัวได้ สมมติว่าเขาต้องโพสต์ไฟล์ หลังจากโพสต์เขาสามารถเรียกใช้ฟังก์ชัน js ที่จะลบและเพิ่มตัวเลือกไฟล์ใหม่ มันทำได้
BrunoLM

3
โปรดทราบว่าเมื่อคุณใช้.attr("value", "")หรือ.val("")(เช่นคำแนะนำโดย @ wagner-leonardi ด้านล่าง) internet explorer จะเริ่มเหตุการณ์การเปลี่ยนแปลงในขณะที่ chrome ไม่
fadomire

4
เนื่องจาก "value" เป็นคุณสมบัติและไม่ใช่แอตทริบิวต์ของอินพุตการใช้ jQuery ที่แนะนำคือ.prop("value", "")
Roger Barreto


50

คุณสามารถตั้งค่าเป็นnullเส้นทางไฟล์ทุกครั้งที่ผู้ใช้คลิกที่ตัวควบคุม ตอนนี้แม้ว่าผู้ใช้จะเลือกไฟล์เดียวกันเหตุการณ์onchangeจะถูกทริกเกอร์

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

2
ฉันต้องการวิธีแก้ปัญหาเช่นนี้ มันสั้นมากและทำงานให้ลุล่วง คิดดี Mariusz Wiazowski
Jay Dharmendra Solanki

ทางออกอื่นคือการเปลี่ยนค่าเมื่อแท็กอินพุตเปลี่ยน แต่เราไม่คาดว่าค่าจะเปลี่ยนแปลงหลังจากเลือกไฟล์
songgeb

1
เจ๋งไปกว่าการลบและเพิ่มองค์ประกอบในโดมอีกแล้วขอบคุณครับ
David Dal Busco

25

ใช้เหตุการณ์ onClick เพื่อล้างค่าของอินพุตเป้าหมายทุกครั้งที่ผู้ใช้คลิกที่ฟิลด์ เพื่อให้แน่ใจว่าเหตุการณ์ onChange จะถูกทริกเกอร์สำหรับไฟล์เดียวกันด้วย ทำงานให้ฉัน :)

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

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

ใช้ TypeScript

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

17

ฉันทำให้สิ่งนี้ทำงานได้โดยการล้างค่าอินพุตไฟล์ onClick จากนั้นโพสต์ไฟล์ onChange สิ่งนี้ช่วยให้ผู้ใช้สามารถเลือกไฟล์เดียวกันสองครั้งติดต่อกันและยังคงมีเหตุการณ์การเปลี่ยนแปลงที่จะโพสต์ไปยังเซิร์ฟเวอร์ ตัวอย่างของฉันใช้ปลั๊กอิน jQuery รูปแบบ

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

onClickไฟไหม้ก่อนonChangeดังนั้นวิธีนี้จึงเหมาะกับฉันมาก
iplus26

8

งานนี้สำหรับฉัน

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

1
ฉันเดาว่าคุณหมายถึงฟังก์ชัน () {this.value = null; กลับเท็จ }
Jacek Pietal

8

โซลูชัน VueJs

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

1
ขอบคุณสำหรับคำตอบรูปแบบนี้
Coisox

6

แรงบันดาลใจจาก @braitsch ฉันใช้สิ่งต่อไปนี้ใน AngularJS2 ของฉัน 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);
    }
}

ที่นี่onClick(event)ช่วยฉัน :-)


4

นี่คือวิธีแก้ปัญหา React-y ที่ฉันพบว่าเหมาะกับฉัน:

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


3

อาจเป็นวิธีที่ง่ายที่สุดที่คุณสามารถทำได้คือตั้งค่าเป็นสตริงว่าง สิ่งนี้บังคับให้ 'เปลี่ยน' ไฟล์ทุกครั้งแม้ว่าจะเลือกไฟล์เดียวกันอีกครั้งก็ตาม

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


2

หากคุณไม่ต้องการใช้ jQuery

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

ใช้งานได้ดีใน Firefox แต่สำหรับ Chrome คุณต้องเพิ่มthis.value=null;หลังจากแจ้งเตือน


2

ตามค่าเริ่มต้นคุณสมบัติค่าขององค์ประกอบอินพุตจะถูกล้างหลังจากการเลือกไฟล์หากอินพุตมีหลายแอตทริบิวต์ หากคุณไม่ทำความสะอาดคุณสมบัตินี้เหตุการณ์ "เปลี่ยนแปลง" จะไม่เริ่มทำงานหากคุณเลือกไฟล์เดียวกัน คุณสามารถจัดการพฤติกรรมนี้โดยใช้multipleแอตทริบิวต์

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

การอ้างอิง


1

คุณไม่สามารถchangeก่อไฟได้ที่นี่ (พฤติกรรมที่ถูกต้องเนื่องจากไม่มีอะไรเปลี่ยนแปลง) อย่างไรก็ตามคุณสามารถผูกได้clickเช่นกัน ... แม้ว่าสิ่งนี้อาจเกิดขึ้นบ่อยเกินไป ... แม้ว่าทั้งสองจะมีพื้นตรงกลางไม่มากนัก

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

ดูเหมือนว่าคุณจะพูดซ้ำคำพูดของเขาและ.click()ไม่ได้ "เริ่มการเลือกใหม่"
BrunoLM

@BrunoLM - ไม่มันไม่ใช่ ... แต่ฉันคิดว่าคุณอ่านส่วนที่ฉันบอกว่าคุณไม่สามารถทำสิ่งนี้clickได้ใกล้เคียงที่สุดเท่าที่จะทำได้
Nick Craver

1

สร้างเหตุการณ์การคลิกและเหตุการณ์การเปลี่ยนแปลงสำหรับป้อนข้อมูล เหตุการณ์การคลิกจะล้างข้อมูลเข้าและเหตุการณ์การเปลี่ยนแปลงจะมีรหัสที่คุณต้องการเรียกใช้

ดังนั้นเหตุการณ์การคลิกจะว่างเปล่าเมื่อคุณคลิกปุ่มอินพุต (ก่อนที่หน้าต่างเลือกไฟล์จะเปิดขึ้น) ดังนั้นเหตุการณ์การเปลี่ยนแปลงจะทริกเกอร์เสมอเมื่อคุณเลือกไฟล์

$("#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

คุณสามารถใช้form.reset()เพื่อล้างข้อมูลไฟล์filesรายการ การดำเนินการนี้จะรีเซ็ตฟิลด์ทั้งหมดเป็นค่าเริ่มต้น แต่ในหลาย ๆ กรณีคุณอาจใช้ประเภทอินพุต = 'file' ในรูปแบบเพื่ออัปโหลดไฟล์เท่านั้น ในโซลูชันนี้ไม่จำเป็นต้องโคลนองค์ประกอบและเชื่อมโยงเหตุการณ์อีกครั้ง

ขอบคุณphiliplehmann


0

ฉันพบปัญหาเดียวกันฉันแดงผ่านทางเขาแก้ปัญหาข้างต้น แต่พวกเขาไม่ได้รับคำอธิบายที่ดีว่าเกิดอะไรขึ้น

โซลูชันนี้ฉันเขียนhttps://jsfiddle.net/r2wjp6u8/ไม่มีการเปลี่ยนแปลงมากมายในโครงสร้าง DOM เพียงแค่เปลี่ยนค่าของช่องป้อนข้อมูล จากด้านประสิทธิภาพน่าจะดีกว่าเล็กน้อย

ลิงก์ไปยังซอ: 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

ดังนั้นไม่มีวิธีใดที่จะแน่ใจได้ 100% ว่าพวกเขากำลังเลือกไฟล์เดียวกันเว้นแต่คุณจะจัดเก็บไฟล์แต่ละไฟล์และเปรียบเทียบโดยใช้โปรแกรม

วิธีที่คุณโต้ตอบกับไฟล์ (JS สิ่งที่ไม่เมื่อผู้ใช้อัปโหลด 'ไฟล์) เป็นAPI HTML5 ไฟล์และJS 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

บทช่วยสอนเหล่านี้จะแสดงวิธีการบันทึกและอ่านข้อมูลเมตา (จัดเก็บเป็นวัตถุ js) เมื่ออัปโหลดไฟล์

สร้างฟังก์ชันที่เรียกใช้ 'onChange' ซึ่งจะอ่าน -> จัดเก็บ -> เปรียบเทียบข้อมูลเมตาของไฟล์ปัจจุบันกับไฟล์ก่อนหน้า จากนั้นคุณสามารถทริกเกอร์เหตุการณ์ของคุณเมื่อเลือกไฟล์ที่ต้องการ


0

เชื่อเถอะว่ามันช่วยคุณได้แน่นอน!

// 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;
};

หวังว่านี่จะช่วยพวกคุณหลาย ๆ คน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.