Чи в JavaScript можна зробити програмний запуск "натискання" програмно для елемента введення файлу?


261

Я хотів би зробити <input type="file">тег події натискання на тег програмно.

Просто виклик click (), схоже, нічого не робить або, принаймні, не відкриває діалогове вікно вибору файлів.

Я експериментував із захопленням подій за допомогою слухачів і перенаправляв подію, але мені не вдалося зробити це, щоб насправді виконати подію так, як хтось натиснув на неї.


1
Подія натискання, яку ви запускаєте, повинна бути викликана в межах події, що розпочалася користувачем, інакше вона не працюватиме.
Умагон

Відповіді:


79

Ви не можете це зробити у всіх браузерах, нібито IE це дозволяє, але Mozilla та Opera цього не роблять.

Коли ви створюєте повідомлення в GMail, функція "приєднувати файли" реалізується одним способом для IE та будь-якого браузера, який підтримує це, а потім реалізується іншим способом для Firefox та тих браузерів, які цього не роблять.

Я не знаю, чому ви не можете цього зробити, але одне, що є ризиком для безпеки, і яке вам заборонено робити в будь-якому браузері, це програмно встановити ім'я файлу на елементі HTML File.


1
Драт. Ну я звичайно розумію, що це корисно. Це десь задокументовано? Я думаю, це було б реалізовано кожним браузером?
користувач28655

Оновлена ​​моя відповідь більш правильною, ніж попередня відповідь - суть однакова, але уточнення має трохи допомогти. Цей хлопець зіткнувся з тією ж проблемою: bytes.com/forum/thread542877.html
Джейсон Бантінг

Слава Богу, FF5 дозволяє цей клік
rshimoda

2
Для уточнення вище коментаря: Chrome нещодавно змінили, щоб перевірити, чи бачиться inputелемент файлу . Запуск clickметоду працює, в тому числі на консолі, якщо елемент можна побачити.
jwadsack

2
@Otvazhnii - чувак, ця відповідь (та, яку ти кажеш, неправильна) - 10 років - не дивно, що вона не правильна! (Я точно не знаю, я приймаю за це ваше слово). : P
Джейсон Бантінг

257

Я цілий день шукав рішення. І ось такі висновки я зробив:

  1. З міркувань безпеки Opera і Firefox не дозволяють запускати введення файлів.
  2. Єдиною зручною альтернативою є створення "прихованого" введення файлу (використовуючи непрозорість, а не "прихований" чи "дисплей: жоден"!), А потім створити кнопку "під ним". Таким чином видно кнопку, але при натисканні користувача вона фактично активує введення файлу.

Сподіваюсь, це допомагає! :)

<div style="display: block; width: 100px; height: 20px; overflow: hidden;">
<button style="width: 110px; height: 30px; position: relative; top: -5px; left: -5px;"><a href="javascript: void(0)">Upload File</a></button>
<input type="file" id="upload_input" name="upload" style="font-size: 50px; width: 120px; opacity: 0; filter:alpha(opacity=0);  position: relative; top: -40px;; left: -20px" />
</div>

6
це рішення чудово працює. Не впевнений, чому це було не помічено і не завищено. Це не * саме те, про що задається питання, але це велика робота. Ви виявили, що це несумісне з будь-якими браузерами? У мене немає часу, щоб я пройшов свій шлях через всі 10+ ароматів відповідних ароматів, щоб перевірити.
Євген Симкін

1
Дякую за цю відповідь, це приголомшливо: D
mario.tco

Приємне рішення. Працює і на мобільному браузері Android.
gstroup

1
Це неправда. Дивіться відповідь Дідьє нижче. Програмне клацання повинно відбуватися з контексту дії користувача, як, наприклад, в обробці кліків іншої кнопки. Тоді це прекрасно працює, не потрібно мати переливного елемента.
смок

1
Єдина проблема з цим полягає в тому, що якщо ви хочете змінити стиль кнопки на наведення курсору, ви не можете. Це означає, що якщо ви хочете, щоб він виглядав як усі інші кнопки у вашому додатку, ви не можете.
Вінсент

68

Ви можете натиснути () на будь-який веб-переглядач, але для деяких браузерів елемент повинен бути видимим та зосередженим. Ось приклад jQuery:

$('#input_element').show();
$('#input_element').focus();
$('#input_element').click();
$('#input_element').hide();

Він працює з приховуванням раніше, click()але я не знаю, чи працює він, не викликаючи метод показу. Ніколи не пробував цього в Opera, я тестував на IE / FF / Safari / Chrome і це працює. Сподіваюся, це допоможе.


51
Дякую, що поділились. На випадок, якщо ви не знали - ви можете використовувати ланцюжок у jQuery: $(...).show().focus().click().hide();:)
pimvdb

1
@pimvdb: наскільки я тестую, ваше рішення працює лише в Chrome.
Хоан Лонг

1
@ Hoàng Long: Ви маєте на увазі рішення ланцюга чи рішення Флоріна Могоса? Я не вірю, що ланцюжок призведе до відмінностей між переглядачами.
pimvdb

1
@ HoàngLong Це працює для мене в IE 8 та 9, останніх Chrome, Safari та Firefox.
Самі Самхурі

2
Дивно. Як я тестував, він не працює під Chrome в Ubuntu.
sandrew

29

ЦЕ МОЖЛИВО: Під FF4 +, Opera ?, Chrome: але:

  1. inputElement.click()слід викликати з контексту дії користувача! (не контекст виконання сценарію)

  2. <input type="file" />має бути видимим ( inputElement.style.display !== 'none') (ви можете приховати це видимістю чи чимось іншим, але не властивістю "відображення")


Це вирішило це для мене. Мені довелося додати javascript до onclickатрибуту замість прив’язки до події.
jasonlfunk

1
Оголошення єдиного розумного рішення. Метод переповнення некрасивий.
smok

Га! Я знав, що це має бути щось із контекстом! Я зауважував, що дзвінки inputElement.click()з події клавіатури (ярлик для вкладення файлу) спрацювали, але виклик його в режимі очікування або зворотного виклику Ajax НЕ. Оголошено.
brettjonesdev

9
У Btw хтось має додаткові ресурси щодо "контексту дії користувача" проти "контексту виконання сценарію"? Все, що я бачу під час пошуку, пов'язане з контекстом виконання та this. : /
brettjonesdev

@bretjonesdev Я думаю, що це означає, що його потрібно виконати всередині ініційованого користувачем обробника подій, як-от обробник подій клацання, проти обіцянки, таймауту чи будь-якої іншої події, ініційованої користувачем.
Алекс Герра

10

Для тих, хто розуміє, що вам потрібно накласти невидиму форму над посиланням, але занадто лінивий писати, я написав це для вас. Ну, для мене, але, можливо, також поділюся. Коментарі вітаються.

HTML (десь):

<a id="fileLink" href="javascript:fileBrowse();" onmouseover="fileMove();">File Browse</a>

HTML (десь вас не цікавить):

<div id="uploadForm" style="filter:alpha(opacity=0); opacity: 0.0; width: 300px; cursor: pointer;">
    <form method="POST" enctype="multipart/form-data">
        <input type="file" name="file" />
    </form>
</div>

JavaScript:

function pageY(el) {
    var ot = 0;
    while (el && el.offsetParent != el) {
        ot += el.offsetTop ? el.offsetTop : 0;
        el = el.offsetParent;
    }
    return ot;
}

function pageX(el) {
    var ol = 0;
    while (el && el.offsetParent != el) {
        ol += el.offsetLeft ? el.offsetLeft : 0;
        el = el.offsetParent;
    }
    return ol;
}

function fileMove() {
    if (navigator.appName == "Microsoft Internet Explorer") {
        return; // Don't need to do this in IE. 
    }
    var link = document.getElementById("fileLink");
    var form = document.getElementById("uploadForm");
    var x = pageX(link);
    var y = pageY(link);
    form.style.position = 'absolute';
    form.style.left = x + 'px';
    form.style.top = y + 'px';
}

function fileBrowse() {
    // This works in IE only. Doesn't do jack in FF. :( 
    var browseField = document.getElementById("uploadForm").file;
    browseField.click();
}



7

Якщо ви хочете, щоб clickметод працював на Chrome, Firefox тощо, застосуйте до вхідного файлу наступний стиль. Це буде ідеально приховано, це як ви робитеdisplay: none;

#fileInput {
    visibility: hidden;
    position: absolute;
    top: 0;
    left: -5000px;
}

Це так просто, я перевірив це працює!


Мені це подобається найкраще, оскільки деякі старі браузери нічого не робитимуть на inputElement.click (), якщо він прихований.
Нік

Чому не просто встановити heightі widthв 0?
Соломон Учко

5
$(document).one('mousemove', function() { $(element).trigger('click') } );

Працював для мене, коли я зіткнувся з подібною проблемою, це звичайний eRube Goldberg.


4

РОБОТА РІШЕННЯ

Дозвольте додати до цієї старої публікації робоче рішення, яке я використовував, і працює, ймовірно, 80% або більше всіх браузерів, як нових, так і старих.

Рішення складне, але просте. Першим кроком є ​​використання CSS та виправдання типу вхідного файлу з "недоелементами", які відображаються через непрозорість 0. Наступним кроком є ​​використання JavaScript для оновлення мітки за потребою.

HTML- ідентифікатори просто вставляються, якщо ви хочете швидкий спосіб отримати доступ до певного елемента, однак класи є обов'язковим, оскільки вони стосуються CSS, який встановлює весь цей процес

<div class="file-input wrapper">
    <input id="inpFile0" type="file" class="file-input control" />
    <div class="file-input content">
        <label id="inpFileOutput0" for="inpFileButton" class="file-input output">Click Here</label>
        <input id="inpFileButton0" type="button" class="file-input button" value="Select File" />
    </div>
</div>

CSS Майте на увазі, кольори та стилі шрифту, і такі - ваші переваги, якщо ви використовуєте цей базовий CSS, ви завжди можете використовувати позначку після закінчення до стилю, як вам подобається, це показано в списку jsFiddle в кінці.

.file-test-area {
    border: 1px solid;
    margin: .5em;
    padding: 1em;
}
.file-input {
    cursor: pointer !important;
}
.file-input * {
    cursor: pointer !important;
    display: inline-block;
}
.file-input.wrapper {
    display: inline-block;
    font-size: 14px;
    height: auto;
    overflow: hidden;
    position: relative;
    width: auto;
}
.file-input.control {
    -moz-opacity:0 ;
    filter:alpha(opacity: 0);
    opacity: 0;

    height: 100%;
    position: absolute;
    text-align: right;
    width: 100%;
    z-index: 2;
}
.file-input.content {
    position: relative;
    top: 0px;
    left: 0px;
    z-index: 1;
}
.file-input.output {
    background-color: #FFC;
    font-size: .8em;
    padding: .2em .2em .2em .4em;
    text-align: center;
    width: 10em;
}
.file-input.button {
    border: none;
    font-weight: bold;
    margin-left: .25em;
    padding: 0 .25em;
}

JavaScript Чистий і правдивий, однак деякі ОСВІТНІ (пенсіонери) браузери все ще можуть мати проблеми з ним (наприклад, Netscrape 2!)

var inp = document.getElementsByTagName('input');
for (var i=0;i<inp.length;i++) {
    if (inp[i].type != 'file') continue;
    inp[i].relatedElement = inp[i].parentNode.getElementsByTagName('label')[0];
    inp[i].onchange /*= inp[i].onmouseout*/ = function () {
        this.relatedElement.innerHTML = this.value;
    };
};

Приклад роботи jsFiddle


4

Це працює :

З міркувань безпеки на Firefox та Opera, ви не можете запустити натискання на введення файлу, але ви можете імітувати за допомогою MouseEvents:

<script>
click=function(element){
    if(element!=null){
        try {element.click();}
        catch(e) {
            var evt = document.createEvent("MouseEvents");
            evt.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,0,null);
            element.dispatchEvent(evt);
            }
        }
    };
</script>

<input type="button" value="upload" onclick="click(document.getElementById('inputFile'));"><input type="file" id="inputFile" style="display:none">

1
Зауважте, що createEvent()і initMouseEvent()тепер застарілі.
Alexis Wilke

4

Я знаю, що це давнє, і всі ці рішення - це злом навколо запобіжних заходів браузера з реальною цінністю.

Однак, fileInput.click () працює на поточному Chrome (36.0.1985.125 м) та поточному ESR Firefox (24.7.0), але не в поточному IE (11.0.9600.17207). Накладання файлового поля з непрозорістю 0 на верхній частині кнопки працює, але я хотів, щоб елемент зв’язку був видимим тригером, і підкреслення курсору не дуже працює в жодному браузері. Він спалахує, а потім зникає, ймовірно, браузер замислюється, чи дійсно така укладка наведення курсора застосовується чи ні.

Але я знайшов рішення, яке працює у всіх цих браузерах. Я не претендую на тестування кожної версії кожного веб-переглядача або знаю, що вона буде працювати назавжди, але, схоже, зараз відповідає моїм потребам.

Це просто: розмістіть поле введення файлу на екрані (позиція: абсолютна; вгорі: -5000px), покладіть навколо нього елемент мітки та натисніть на ярлик замість самого поля файлу.

Зауважте, що для виклику методу клацання мітки потрібно сценаріювати посилання, але це не робиться автоматично, як при натисканні на текст всередині елемента мітки. Мабуть, елемент посилання фіксує клацання, і він не переходить до мітки.

Зауважте також, що це не забезпечує спосіб відображення обраного на даний момент файлу, оскільки поле є поза екраном. Я хотів подати негайно, коли був обраний файл, тому для мене це не проблема, але вам потрібен дещо інший підхід, якщо ваша ситуація відрізняється.


Гаразд, тег кнопок, onclick = "filetag.click ()" не працює з IE 9 та 10 (але працює з IE 11, Firefox 4/10/26/27/28, Chrome / Chromium 31/32/33 / 36, Сафарі 7, Опера 23). Але, якщо ви використовуєте мітку для = "id-of-file-input" (без onlick), вона працює для IE 9/10/11.
luigifab

4

JS Fiddle: http://jsfiddle.net/eyedean/1bw357kw/

popFileSelector = function() {
    var el = document.getElementById("fileElem");
    if (el) {
        el.click();  
    }
};

window.popRightAway = function() {
    document.getElementById('log').innerHTML += 'I am right away!<br />';
    popFileSelector();
};

window.popWithDelay = function() {
    document.getElementById('log').innerHTML += 'I am gonna delay!<br />';
    window.setTimeout(function() {
        document.getElementById('log').innerHTML += 'I was delayed!<br />';
        popFileSelector();
    }, 1000);
};
<body>
  <form>
      <input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)" />
  </form>
  <a onclick="popRightAway()" href="#">Pop Now</a>
    <br />
  <a onclick="popWithDelay()" href="#">Pop With 1 Second Delay</a>
    <div id="log">Log: <br /></div>
</body>


3

Цей код працює для мене. Це те, що ви намагаєтесь зробити?

<input type="file" style="position:absolute;left:-999px;" id="fileinput" />
<button  id="addfiles" >Add files</button>

<script language="javascript" type="text/javascript">
   $("#addfiles").click(function(){
      $("#fileinput").click();
   });
</script>

3

Моє рішення для Safari з jQuery та jQuery-ui:

$("<input type='file' class='ui-helper-hidden-accessible' />").appendTo("body").focus().trigger('click');

заголовки вгору: не працює для firefox 33, chrome 38. тригер ("клацання") може працювати лише в контексті події взаємодії користувача - обробники подій.
Аміт G

3

Ось чисте JavaScript вирішення цієї проблеми. Добре працює у всіх браузерах

<script>
    function upload_image_init(){
        var elem = document.getElementById('file');
        if(elem && document.createEvent) {
           var evt = document.createEvent("MouseEvents");
           evt.initEvent("click", true, false);
           elem.dispatchEvent(evt);
        }
    }
</script>

2

Існують способи перенаправити події на контроль, але не сподівайтеся, що ви зможете легко запускати події до управління пожежею, оскільки браузери намагатимуться заблокувати це з (доброї) причини безпеки.

Якщо вам потрібне діалогове вікно для відображення лише тоді, коли користувач щось натискає, скажімо, тому, що ви хочете краще виглядати кнопки завантаження файлів, тоді ви можете поглянути на те, що придумав Shaun Inman .

Мені вдалося домогтися спрацьовування клавіатури з творчим зміщенням фокусу в та поза контролем між подіями клавіш, натисканням клавіш та клавіатурою. YMMV.

Моя щира порада - залишити це в спокої, тому що це світ браузерної несумісності-болю. Незначні оновлення браузера можуть також блокувати хитрощі без попередження, і вам, можливо, доведеться продовжувати винаходити хаки, щоб продовжувати працювати.


2

Я досліджував це деякий час тому, тому що хотів створити спеціальну кнопку, яка відкрила б діалогове вікно файлів і негайно розпочала завантаження. Я щойно помітив щось, що може зробити це можливим - firefox, здається, відкриває діалогове вікно, коли ви натискаєте будь-яке місце для завантаження. Тож це можуть зробити:

  1. Створіть файл завантаження та окремий елемент, що містить зображення, яке ви хочете використовувати як кнопку
  2. Розташуйте їх, щоб вони перекривались і робили елемент файлу заднім числом та рамкою прозорими, щоб кнопка була єдиною, що видно
  3. Додайте javascript, щоб IE відкрив діалогове вікно при натисканні кнопки / введення файлу
  4. Використовуйте подію зміни, щоб подати форму, коли вибрано файл

Це лише теоретично, оскільки я вже використовував інший метод для вирішення проблеми, але він просто може спрацювати.


2

я маю <input type="button"> тег, прихований від перегляду. Що я зробив - приєднав "onClick"подію до будь-якого видимого компонента будь-якого типу, наприклад, до мітки. Це було зроблено за допомогою Інструментів для розробників Google Chrome або Firebug Mozilla Firefox, використовуючи команду «редагувати HTML» правою кнопкою миші. У цьому випадку вкажіть наступний сценарій або щось подібне:

Якщо у вас є JQuery:

$('#id_of_component').click();

якщо ні:

document.getElementById('id_of_component').click();

Дякую.


2

Гей, це рішення працює. для завантаження нам слід використовувати MSBLOB

$scope.getSingleInvoicePDF = function(invoiceNumberEntity) {
   var fileName = invoiceNumberEntity + ".pdf";
   var pdfDownload = document.createElement("a");
   document.body.appendChild(pdfDownload);

   AngularWebService.getFileWithSuffix("ezbillpdfget",invoiceNumberEntity,"pdf" ).then(function(returnedJSON) {
       var fileBlob = new Blob([returnedJSON.data], {type: 'application/pdf'});
       if (navigator.appVersion.toString().indexOf('.NET') > 0) { // for IE browser
           window.navigator.msSaveBlob(fileBlob, fileName);
       } else { // for other browsers
           var fileURL = window.URL.createObjectURL(fileBlob);
           pdfDownload.href = fileURL;
           pdfDownload.download = fileName;
           pdfDownload.click();      
       }
   });
};

Для AngularJS або навіть для звичайного javascript.


1

Тепер це стане можливим у Firefox 4, із застереженням, яке воно вважається спливаючим вікном, і тому воно буде заблоковано, коли б спливаюче вікно було б.


2
Насправді firefox4 значно покращує стан завантаження файлів. Моя проблема - як зробити те саме в браузері Google Chrome.
erick2red

1

Ось рішення, яке працює для мене: CSS:

#uploadtruefield {
    left: 225px;
    opacity: 0;
    position: absolute;
    right: 0;
    top: 266px;
    opacity:0;
    -moz-opacity:0;
    filter:alpha(opacity:0);
    width: 270px;
    z-index: 2;
}

.uploadmask {
    background:url(../img/browse.gif) no-repeat 100% 50%;
}
#uploadmaskfield{
    width:132px;
}

HTML з "малою" довідкою JQuery:

<div class="uploadmask">
    <input id="uploadmaskfield" type="text" name="uploadmaskfield">
</div>
<input id="uploadtruefield"  type="file" onchange="$('#uploadmaskfield').val(this.value)" >

Просто переконайтеся, що замасковане покрито повною мірою справжнім полем завантаження.



1

Я виявив, що якщо введення (файл) знаходиться поза формою, то при запуску події клацання викликає діалогове вікно файлу.


1

Сподіваюсь, це допомагає комусь - я провів 2 години, стукаючи головою об це:

У IE8 або IE9, якщо ви спровокуєте відкриття файлового введення з JavaScript будь-яким способом (повірте, я їх все випробував), він не дозволить вам надіслати форму за допомогою javascript, вона просто мовчки вийде з ладу.

Подання форми за допомогою звичайної кнопки надсилання може працювати, але зателефонувавши до form.submit (); буде мовчки виходити з ладу.

Мені довелося вдатися до накладання кнопки вибору файлу з прозорим вводом файлу, який працює.


Крім того, ви можете загортати введення файлу в мітку, так що в IE ви можете отримати мітку, що може натискати мітку, щоб охопити всю область кнопок, тоді як за допомогою лише тегу введення файлу лише половина його можна натискати в IE.
галати

1

Це працювало для мене:

<script>
    function sel_file() {
        $("input[name=userfile]").trigger('click');
    }  
</script>

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

<a href="javascript:sel_file();">Click</a>

1

це не неможливо:

var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);  
setTimeout(function(){ document.getElementById('input_field_id').dispatchEvent(evObj); },100);

Але якимось чином це працює лише в тому випадку, якщо це функція, яку викликали через подія click.

Тож у вас може бути наступне налаштування:

html:

<div onclick="openFileChooser()" class="some_fancy_stuff">Click here to open image chooser</div>
<input type="file" id="input_img">

JavaScript:

    function openFileChooser() {
      var evObj = document.createEvent('MouseEvents');
      evObj.initMouseEvent('click', true, true, window);  
      setTimeout(function()
      { 
        document.getElementById('input_img').dispatchEvent(evObj);      
      },100);      
    }

createEvent()І initMouseEvent()були застарілими. Ви повинні скористатися CustomEvent()зараз ...
Alexis Wilke

0

Можна використовувати

<button id="file">select file</button>
<input type="file" name="file" id="file_input" style="display:none;">
<script>
$('#file').click(function() {
        $('#file_input').focus().trigger('click');
    });
</script>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.