Mở hộp thoại tệp bằng JavaScript


109

Tôi cần một giải pháp để hiển thị hộp thoại tệp đang mở trong HTML khi nhấp vào a div. Hộp thoại mở tệp phải mở khi divđược nhấp.

Tôi không muốn hiển thị hộp tệp đầu vào như một phần của trang HTML. Nó phải được hiển thị trong hộp thoại riêng biệt, không phải là một phần của trang web.


4
Một cảnh báo không phải là một hộp thoại tệp? - Bạn có thể làm rõ những gì bạn đang hỏi không?
LiamB

3
tôi nghĩ rằng ông đang nói ông muốn tiêu chuẩn "tập tin mở" cửa sổ bật lên
Valentin Rocher

1
tôi cần mở hộp thoại tệp khi một div được nhấp vào. nó phải giống như cảnh báo không phải là một phần của trang web
ArK

Câu trả lời:


52

Đây là một cái hay

Bản trình diễn Trình tải lên tốt

Nó là một sự <input type='file' />kiểm soát chính nó. Nhưng một div được đặt trên đó và các kiểu css được áp dụng để có được cảm giác đó. Độ mờ của điều khiển tệp được đặt thành 0 để xuất hiện cửa sổ hộp thoại được mở khi nhấp vào div.


1
là có một cách để kiểm soát các tập tin hiển thị bằng javascript ... nói rằng tôi muốn hộp thoại mở tập và chỉ mở rộng tập tin muốn với .pdf để hiển thị ..
Ajax3.14

1
@ Ajax3.14 các trình duyệt mới có đối tượng FileReader, các trình duyệt cũ bạn phải sử dụng giá trị và tìm kiếm phần mở rộng tệp.
Vicary

2
@ Ajax3.14 Không cần sử dụng FileReader hoặc phần mở rộng phân tích cú pháp. Nhiều trình duyệt hỗ trợ thuộc tính accept trên đầu vào tệp. Điều này cho phép bạn giới hạn các loại tệp được hiển thị trong hộp thoại trình duyệt tệp. Fine Uploader cung cấp quyền truy cập vào chức năng này thông qua thuộc tính acceptFiles của tùy chọn xác thực. Xem phần xác thực của tài liệu tùy chọn để biết thêm chi tiết. Lưu ý rằng thuộc tính accept không được hỗ trợ trong IE9 hoặc phiên bản cũ hơn.
Ray Nicholus

1
làm thế nào mà điều này là tốt? đây là một thực hành tốt ở tất cả? không nên giống như thế này: stackoverflow.com/a/18659941/915865 ?
Kat Lim Ruiz

1
@KatLimRuiz Không, câu trả lời bạn đã liên kết không phải là một giải pháp tốt. Điều này sẽ khiến IE gặp lỗi nếu bạn cũng gửi biểu mẫu được liên kết theo chương trình.
Ray Nicholus

77

    $("#logo").css('opacity','0');
    
    $("#select_logo").click(function(e){
       e.preventDefault();
       $("#logo").trigger('click');
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" id="select_logo">Select Logo</a> <input type="file" id="logo">

cho IE thêm cái này:

$("#logo").css('filter','alpha(opacity = 0');

3
Tại sao bạn trả về false trong trình xử lý nhấp chuột #select_logo?
Sethish

4
Nó sẽ không tạo ra lỗi 404, nó sẽ chỉ thử và điều hướng đến trang hiện tại, với # được thêm vào cuối. Điều này sẽ làm cho trang chuyển lên đầu. Vì vậy, thật tốt khi ở đó, chỉ vì một lý do khác :)
manavo

3
Mặc dù tôi chưa kiểm tra nó đủ, "khả năng hiển thị: ẩn;" có vẻ tương thích hơn. Ngoài ra, bất chấp độ mờ: 0, một sự kiện nhấp chuột sẽ kích hoạt nếu phần tử "ẩn" được nhấp vào, trong khi khả năng hiển thị: ẩn sẽ không.
Aron

MDN chỉ ra rằng document.getElementById("logo").click()là đủ. Họ cũng hiển thị một cách khác "Kéo & Thả". developer.mozilla.org/en-US/docs/Web/API/File/…
Eric

2
Bạn nên chuyển đổi này để Javascript bình thường, JQuery isnt logic để sử dụng trên một dự án nhỏ như vậy ^ _ ^
Mister SirCode

57

Tôi không biết tại sao không ai chỉ ra điều này nhưng đây là một cách thực hiện mà không cần bất kỳ Javascript nào và nó cũng tương thích với bất kỳ trình duyệt nào.


CHỈNH SỬA: Trong Safari, tính năng này inputbị vô hiệu hóa khi ẩn với display: none. Một cách tiếp cận tốt hơn sẽ là sử dụng position: fixed; top: -100em.


<label>
  Open file dialog
  <input type="file" style="position: fixed; top: -100em">
</label>

Nếu bạn muốn, bạn có thể đi theo "cách chính xác" bằng cách sử dụng fortrong labeltrỏ tới idđầu vào như sau:

<label for="inputId">file dialog</label>
<input id="inputId" type="file" style="position: fixed; top: -100em">

4
điều này hoạt động giống như sự quyến rũ, tuy nhiên, đây là một số khuyến nghị: 1. <input>thẻ nên có namethuộc tính; 2. nếu forthuộc tính được chỉ định, <input>thẻ tệp sẽ yêu cầu a id.
Raptor

5
Simplicity is the ultimate sophistication
ncubica,

2
tuyệt quá! nó hoạt động giống như một sự quyến rũ ngay cả với hình nền hoặc làm cho nhãn nhận được javascript nhấp chuột được kích hoạt. Cảm ơn!
Leo Nomdedeu 14/10/15

2
BTW, ai đó đã chỉ ra một điểm với giải pháp này, trong Safari, các đầu vào bị ẩn với display: nonebị vô hiệu hóa. Cách giải quyết là sử dụng một cách tiếp cận khác để ẩn đầu vào. Tôi sẽ cập nhật câu trả lời để phản ánh điều đó.
JP de la Torre

1
@JPdelaTorre Sẽ tốt hơn nếu bạn sử dụng opacity: 0 để ẩn đầu vào.
Adrian

39

Trên thực tế, bạn không cần tất cả những thứ đó với độ mờ, khả năng hiển thị, <input>kiểu dáng, v.v. Chỉ cần xem:

<a href="#">Just click me.</a>
<script type="text/javascript">
    $("a").click(function() {
        // creating input on-the-fly
        var input = $(document.createElement("input"));
        input.attr("type", "file");
        // add onchange handler if you wish to get the file :)
        input.trigger("click"); // opening dialog
        return false; // avoiding navigation
    });
</script>

Demo trên jsFiddle . Đã thử nghiệm trong Chrome 30.0 và Firefox 24.0. Tuy nhiên, không hoạt động trong Opera 12.16.


3
Đây phải là câu trả lời chính xác. Để triển khai Javascript thuần túy, không cần sửa đổi bất kỳ mã HTML nào.
Zhang Buzz

21
Câu hỏi ngớ ngẩn, nhưng làm thế nào bạn sẽ có được tệp đã chọn sau đó?
Jay Wick

2
Đây là một giải pháp nguy hiểm có thể phát sinh các vấn đề không mong muốn. Ví dụ: một số trình duyệt (chẳng hạn như IE) có thể ngăn gửi biểu mẫu có lập trình nếu đầu vào tệp cũng được mở theo chương trình. Cách tốt nhất để giải quyết vấn đề này là với CSS, không phải JavaScript.
Ray Nicholus

3
@Charleston Thật không may, nó không hoạt động trong một số trình duyệt. Họ nên làm cho nó hoạt mặc dù :)
Tigran Saluev

3
Tính đến năm 2020, giải pháp này có vẻ là tốt nhất. Đã thử nghiệm nó trên BrowserStack trong Edge, Safari, Opera, Firefox và Chrome. Hoạt động trong tất cả chúng.
V. Rubinetti

14

Đây là những gì hoạt động tốt nhất đối với tôi (Đã thử nghiệm trên IE8, FF, Chrome, Safari).

#file-input {
  cursor: pointer;
  outline: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  overflow: hidden;
  filter: alpha(opacity=0); /* IE < 9 */
  opacity: 0;
}
.input-label {
  cursor: pointer;
  position: relative;
  display: inline-block;
}
<label for="file-input" class="input-label">
  Click Me <!-- Replace with whatever text or icon you wish to use -->
  <input type="file" id="file-input">
</label>

Giải thích: Tôi đã định vị đầu vào tệp ngay phía trên phần tử được nhấp, vì vậy bất kỳ lần nhấp nào cũng sẽ đến trên nó hoặc nhãn của nó (điều này sẽ kéo hộp thoại tải lên giống như khi bạn nhấp vào chính nhãn đó). Tôi đã gặp một số vấn đề với phần nút của đầu vào mặc định nhô ra khỏi cạnh của nhãn, vì vậy overflow: hiddenphần đầu vào và display: inline-blocktrên nhãn là cần thiết.


1
Tối đa hóa đầu vào và đặt độ mờ bằng không. Điều đó hoạt động tuyệt vời!
Kinorsi

13

Điều gì sẽ xảy ra nếu javascript bị Tắt trên máy khách? Sử dụng giải pháp sau cho tất cả các tình huống. Bạn thậm chí không cần javascript / jQuery. :

HTML

<label for="fileInput"><img src="File_upload_Img"><label>
<input type="file" id="fileInput"></label>

CSS

#fileInput{opacity:0}  
body{
    background:cadetblue;
}

Giải thích: for="Your input Id". Kích hoạt sự kiện nhấp chuột theo mặc định theo HTML. Vì vậy, nó mặc định kích hoạt sự kiện nhấp chuột, không cần jQuery / javascript. Nếu nó được thực hiện đơn giản bằng HTML tại sao lại sử dụng jQuery / jScript? Và bạn không thể biết liệu khách hàng có tắt JS hay không. Tính năng của bạn sẽ hoạt động ngay cả khi JS bị tắt.

Làm việc jsFiddle (Bạn không cần JS, jquery)


3
Tại sao nền?
Solomon Ucko

12

Đầu tiên hãy thêm vào các thẻ head :

<script>
   function showDialog(openFileDialog) {
       document.getElementById(openFileDialog).click();
   }
   function fileName(openFileDialog) {
       return document.getElementById(openFileDialog).value;
   }
   function hasFile(openFileDialog) {
       return document.getElementById(openFileDialog).value != "";
   }
   function fileNameWithoutFakePath(openFileDialog) {
       var fileName = document.getElementById(openFileDialog).value;
       return fileName.substr(fileName.lastIndexOf('\\') + 1);
   }
   function fakePathWithoutFileName(openFileDialog) {
       var fileName = document.getElementById(openFileDialog).value;
       return fileName.substr(0, fileName.lastIndexOf('\\'));
   }
</script>

nếu bạn đã có các thẻ script , chỉ cần thêm các chức năng này ở trên.

Trong cơ thể hoặc thẻ biểu mẫu của bạn thêm:

<input type="file" style="display:none" id="yourDesiredOrFavoriteNameForTheNewOpenFileDialogInstance"/>

Không có vấn đề gì trong html của bạn, giống như bạn đã tạo một phiên bản mới của loại OpenFileDialog lớp làm biến toàn cục, có tên là id của phần tử, bất kể ở đâu trong mã hoặc xaml, nhưng trong tập lệnh hoặc mã của bạn , bạn không thể nhập tên của anh ấy, rồi đọc một thuộc tính hoặc gọi một hàm, vì có những hàm toàn cục thực hiện những hàm đó không được xác định trong phần tử input type = "file". Bạn chỉ cần cung cấp cho các hàm này id của kiểu đầu vào ẩn = "tệp" là tên của cá thể OpenFileDialog dưới dạng chuỗi.

Để giúp bạn dễ dàng hơn trong việc tạo các phiên bản hộp thoại tệp mở cho html của mình, bạn có thể tạo một hàm thực hiện điều đó:

function createAndAddNewOpenFileDialog(name) {
     document.getElementById("yourBodyOrFormId").innerHtml += "<input type='file' style='display:none' id='" + name + "'/>"
}

và nếu bạn muốn loại bỏ hộp thoại tệp đang mở, thì bạn có thể tạo và sử dụng chức năng sau:

function removeOpenFileDialog(name) {
    var html = document.getElementById("yourBodyOrFormId").innerHtml;
    html = html.replace("<input type='file' style='display:none' id='" + name + "'/>", "");
    document.getElementById("yourBodyOrFormId").innerHtml = html;
}

nhưng trước khi bạn xóa hộp thoại tệp đang mở, hãy đảm bảo rằng hộp thoại đó tồn tại bằng cách tạo và sử dụng hàm sau:

function doesOpenFileDialogExist(name) {
    return document.getElementById("yourBodyOrFormId").innerHtml.indexOf("<input type='file' style='display:none' id='" + name + "'/>") != -1
}

và nếu bạn không muốn để tạo ra và thêm các hộp thoại tập tin mở trong cơ thể hoặc dạng thẻ trong html, bởi vì đây là thêm ẩn input type = "file" s, sau đó bạn có thể làm điều đó trong kịch bản bằng cách sử dụng chức năng tạo ra ở trên :

function yourBodyOrFormId_onload() {
    createAndAddNewOpenFileDialog("openFileDialog1");
    createAndAddNewOpenFileDialog("openFileDialog2");
    createAndAddNewOpenFileDialog("openFileDialog3");
    createAndAddNewOpenFileDialog("File Upload");
    createAndAddNewOpenFileDialog("Image Upload");
    createAndAddNewOpenFileDialog("bla");
    //etc and rest of your code
}

Đảm bảo rằng gần thẻ body hoặc thẻ biểu mẫu của bạn, bạn đã thêm:

onload="yourBodyOrFormId_onload()"

Bạn không cần phải làm dòng này ở trên, nếu bạn đã làm.

MẸO: Bạn có thể thêm vào dự án hoặc trang web của mình Tệp JScript mới, nếu bạn chưa có, và trong tệp này, bạn có thể đặt tất cả các chức năng hộp thoại tệp đang mở khỏi các thẻ tập lệnh và trang html hoặc trang web, và sử dụng chúng trong html hoặc trang biểu mẫu web của bạn từ tệp JScript này, nhưng đừng quên trước đó liên kết trang html hoặc trang biểu mẫu web với Tệp JScript. Bạn có thể làm điều đó chỉ bằng cách kéo tệp JScript vào trang html của bạn trong đầucác thẻ. Nếu trang của bạn là dạng web chứ không phải html đơn giản và bạn không có thẻ head, thì hãy đặt nó ở bất kỳ đâu để nó có thể hoạt động. Đừng quên xác định biến toàn cục trong Tệp JScript đó, giá trị của nó sẽ là nội dung hoặc id biểu mẫu của bạn dưới dạng chuỗi. Sau khi bạn liên kết tệp JScript với trang html hoặc trang biểu mẫu web của mình, bạn có thể tải lên sự kiện của nội dung biểu mẫu, đặt giá trị của biến đó thành nội dung hoặc id biểu mẫu của bạn. Sau đó, trong Tệp JScript, bạn không cần phải cung cấp cho tài liệu id của nội dung hoặc biểu mẫu của một trang nữa, chỉ cần cung cấp cho nó giá trị của biến đó. Bạn có thể gọi đó là biến bodyId hoặc formId hoặc bodyOrFormId hoặc bất kỳ tên khác mà bạn muốn.

Chúc bạn may mắn!


1
Tốt nhất là không nên sửa đổi trực tiếp InternalHTML.
Solomon Ucko

9

Cách đơn giản nhất:

#file-input {
  display: none;
}
<label for="file-input">
  <div>Click this div and select a file</div>
</label>
<input type="file" id="file-input"/>

Điều quan trọng, việc sử dụng display: noneđảm bảo rằng không có vị trí nào sẽ bị chiếm bởi đầu vào tệp ẩn (điều gì xảy ra khi sử dụng opacity: 0).


3

AFAIK bạn vẫn cần một <input type="file">phần tử, sau đó bạn có thể sử dụng một số công cụ từ mã quirksmode để tạo kiểu cho nó


2

Cách duy nhất không có <input type="file">là nhúng một đoạn phim flash trong suốt lên div. Sau đó, bạn có thể sử dụng sự kiện nhấp chuột do người dùng tạo (tuân thủ 10 quy tắc bảo mật mới của Flash) để kích hoạt lệnh gọi đến FileReference.browse của flash .

Nó cung cấp một sự phụ thuộc bổ sung theo cách quirksmode nhưng đổi lại bạn nhận được nhiều sự kiện hơn (chẳng hạn như các sự kiện được xây dựng trong tiến trình).


-1

Có thể sử dụng

$('<input type="file" />').click()

trong trường hợp của tôi, điều này gây ra chuyển hướng tự động đến cùng một trang đã xảy ra sự kiện nhấp chuột ban đầu - khiến toàn bộ trang tải lại và mất tất cả dữ liệu đã nhập trước đó trong trang.
Muntasir
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.