Cách kích hoạt tải xuống tệp khi nhấp vào nút HTML hoặc JavaScript


433

Điều này thật điên rồ nhưng tôi không biết làm thế nào để làm điều này và vì mức độ phổ biến của các từ này, thật khó để tìm thấy những gì tôi cần trên các công cụ tìm kiếm. Tôi nghĩ rằng đây là một câu trả lời dễ dàng.

Tôi muốn tải xuống tập tin đơn giản, sẽ làm như vậy:

<a href="file.doc">Download!</a>

Nhưng tôi muốn sử dụng nút HTML, ví dụ:

<input type="button" value="Download!">
<button>Download!</button>

Tương tự như vậy, có thể kích hoạt tải xuống đơn giản qua JavaScript không?

$("#fileRequest").click(function(){ /* code to download? */ });

Tôi chắc chắn không tìm cách tạo ra một cái neo trông giống như một nút, sử dụng bất kỳ tập lệnh back-end nào, hoặc gây rối với các tiêu đề máy chủ hoặc các loại mime.


15
Nhờ bạn "cách kích hoạt tải xuống tệp trong javascript" sẽ cung cấp câu trả lời nhanh hơn nhiều cho bất kỳ người tìm kiếm nào trong tương lai.
Thủy thủ Danubian

Câu trả lời:


278

Đối với nút bạn có thể làm

<form method="get" action="file.doc">
   <button type="submit">Download!</button>
</form>

Bạn có thể lưu thẻ biểu mẫu và chỉ cần thêm một onclick vào thẻ nút.
Florian Leit Quay

12
không hoạt động như một trình kích hoạt, chỉ cần chuyển hướng đến url dưới dạng thẻ 'a'.
fdrv

7
Điều này hoạt động tốt hơn: <a href="path_to_file" download="proposed_file_name"> Tải xuống </a>
kscius

11
@kscius thậm chí ngày nay thuộc tính tải xuống không được hỗ trợ trong IE 11 (hiện tại nó được hỗ trợ trong Edge) và nó không được hỗ trợ trong Safari. Vào năm 2012 khi câu trả lời ban đầu được đăng, nó không được hỗ trợ trong bất kỳ trình duyệt chính nào.
Cfreak

1
sự khác biệt giữa việc có một mỏ neo với kiểu dáng nút và có một hình thức với một nút là gì?
Andrei Epure

443

Bạn có thể kích hoạt tải xuống với downloadthuộc tính HTML5 .

<a href="path_to_file" download="proposed_file_name">Download</a>

Ở đâu:

  • path_to_filelà một con đường mà giải quyết đến một URL trên cùng một nguồn gốc . Điều đó có nghĩa là trang và tệp phải chia sẻ cùng một tên miền, tên miền phụ, giao thức (HTTP so với HTTPS) và cổng (nếu được chỉ định). Các ngoại lệ là blob:data:(luôn luôn hoạt động) và file:(không bao giờ hoạt động).
  • proposed_file_namelà tên tệp để lưu vào. Nếu nó trống, trình duyệt mặc định là tên của tệp.

Tài liệu: MDN , Tiêu chuẩn HTML khi tải xuống , Tiêu chuẩn HTML trêndownload , CanIUse


37
Không hoạt động với Safari và một số phiên bản IE nhất định
Mohamed Hussain

4
Sử dụng kết hợp downloadtarget="_blank"dường như là đủ để bao gồm hầu hết các trường hợp sử dụng. Các trình duyệt hiểu downloadnó coi là một bản tải xuống, nếu không thì nó đã được mở trong một tab mới.
MK10

10
Làm thế nào điều này có thể được áp dụng cho một đối tượng nút thay vì chỉ một thẻ ?
bão_m2138

8
Trên thực tế, điều này chỉ hoạt động đối với các url có cùng nguồn gốc như được đề cập trong các tài liệu MDN. Đây là một hạn chế rất lớn nếu chúng tôi đang tìm cách phát triển một giải pháp chung
Akshat Gupta

6
Câu hỏi rõ ràng là yêu cầu sử dụng nút thay vì liên kết
Quentin

86

HTML:

<button type="submit" onclick="window.open('file.doc')">Download!</button>

8
Giải pháp tốt nhất và sạch nhất. Nhưng bạn không cần thêm Javascript ở đây. Phần HTML với onclick là đủ.
Florian Leit Quay

4
Nếu tôi muốn tải xuống một tệp xml thì sao?
g07kore

2
Cảm ơn mã của bạn. Tôi đã thử nghiệm, nó có thể hoạt động trong IE, Chrome, Firefox.
muthukumar

6
Nếu trình duyệt của bạn có tệp được chấp nhận như PDF, nó sẽ mở trong tab mới để hiển thị hộp thoại tải xuống.
WindRider

1
window.open có thể kích hoạt chặn cửa sổ bật lên trong trình duyệt và do đó không được khuyến khích. Bạn có thể sử dụng window.location = 'path', mặc dù điều đó sẽ đi đến vị trí trong cùng một cửa sổ trình duyệt.
Elendurwen

68

Với jQuery:

$("#fileRequest").click(function() {
    // // hope the server sets Content-Disposition: attachment!
    window.location = 'file.doc';
});

1
Hoàn hảo, cảm ơn. Bạn có tình cờ biết liệu hầu hết các máy chủ sẽ đặt Bố trí nội dung thành 'tệp đính kèm' theo mặc định không?
brentonstrine

5
Không có "nhất". Nó hoàn toàn phụ thuộc. Đừng dựa vào nó đang được thiết lập.
Matt Ball

3
Vấn đề này đã thúc đẩy tôi theo đường đạn đạo và đây là lựa chọn duy nhất có hiệu quả (và được IE hỗ trợ). Tôi sẽ thêm cho bất kỳ n00bs nào như tôi để đặt Bố trí nội dung, tất cả những gì bạn phải làm là: <? Tiêu đề php ('Xử lý nội dung: tệp đính kèm; filename = "filename.here"'); ?>
dùng124384

3
Không có jquery. Giai đoạn = Stage.
Adam Arold

1
Công việc này sẽ hoạt động nếu bạn đang cố tải xuống một hình ảnh, nó sẽ mở hình ảnh trong trình duyệt
Dheeraj

34

Chủ đề cũ nhưng nó thiếu một giải pháp js đơn giản:

let a = document.createElement('a')
a.href = item.url
a.download = item.url.split('/').pop()
document.body.appendChild(a)
a.click()
document.body.removeChild(a)

24
@NicholasKyriakides Loại nhắc nhở tôi về viên ngọc này: image.ibb.co/dtkUWJ/Selection_002.png
Stefanos Chrs

@BryanLarsen phiên bản nào của FF?
Stefanos Chrs

1
@BryanLarsen Bạn nói đúng, Firefox không cho phép điều này mà không cần thêm phần tử vào phần thân trước. Cảm ơn bạn, cập nhật câu trả lời
Stefanos Chrs

1
Có cách nào để chức năng javascript được kích hoạt sau khi quá trình tải xuống kết thúc không? Chỉ cần cố gắng hiển thị một thông báo khi quá trình tải xuống bắt đầu và xóa tin nhắn sau khi quá trình tải xuống hoàn tất.
mohit bansal

1
@mohitbansal (un) may mắn là không ở cấp độ trình duyệt
Stefanos Chrs 22/03/19

23

Bạn có thể làm điều đó với "mẹo" với iframe vô hình. Khi bạn đặt "src" cho nó, trình duyệt sẽ phản ứng như thể bạn sẽ nhấp vào một liên kết có cùng "href". Ngược lại với giải pháp với hình thức, nó cho phép bạn nhúng logic bổ sung, ví dụ kích hoạt tải xuống sau khi hết thời gian, khi một số điều kiện được đáp ứng, v.v.

Nó cũng rất im lặng, không có cửa sổ / tab mới nhấp nháy như khi sử dụng window.open.

HTML:

<iframe id="invisible" style="display:none;"></iframe>

Javascript:

function download() {
    var iframe = document.getElementById('invisible');
    iframe.src = "file.doc";
}

Nó, ít nhất là nếu bạn thực sự chấp nhận iframe vào document.body.
yxhuvud

1
Điều này dường như không hoạt động trong Chrome ngay bây giờ, mặc dù nó đã từng hoạt động. Tôi tự hỏi nếu loại này không liên tục ngừng hoạt động trong các phiên bản Chrome khác nhau.
Dobes Vandermeer

Hoạt động trong Chrome kể từ Phiên bản 61.0.3163.100 (Bản dựng chính thức) (64-bit)
AndrewBenjamin

Không hoạt động với hình ảnh trong Firefox v57. Nó chỉ hiển thị hình ảnh trong iframe.
Antony

15

Phiên bản Bootstrap

<a class="btn btn-danger" role="button" href="path_to_file"
   download="proposed_file_name">
  Download
</a>

Tài liệu trong tài liệu Bootstrap 4 và cũng hoạt động trong Bootstrap 3.


9
Điều duy nhất phải làm với Bootstrap là tên lớp, đó chỉ là sức mạnh của HTML5.
Machado

3
Câu hỏi rõ ràng là hỏi làm thế nào để làm điều này với một nút thay vì một liên kết.
Quentin

2
nếu bạn biết bất cứ điều gì về bootstrap, bạn sẽ thấy đó là một nút.
John Lord

11

Tôi nghĩ rằng đây là giải pháp bạn đang tìm kiếm

<button type="submit" onclick="window.location.href='file.doc'">Download!</button>

Tôi có một trường hợp Javascript của tôi tạo tệp CSV. Vì không có URL từ xa để tải xuống nên tôi sử dụng cách thực hiện sau.

downloadCSV: function(data){
    var MIME_TYPE = "text/csv";

    var blob = new Blob([data], {type: MIME_TYPE});
    window.location.href = window.URL.createObjectURL(blob);
}

trên 404 -> thay đổi trang thành trang lỗi 404. vấn đề tương tự như đã nêu trên các location.hrefgiải pháp khác .
BananaAcid

9

Thế còn:

<input type="button" value="Download Now!" onclick="window.location = 'file.doc';">

5
Điều này không hoạt động, ví dụ, nếu tệp của bạn là một hình ảnh, vì nó sẽ chỉ được mở trong trình duyệt.
Juggernaut

Một vấn đề khác xảy ra là nếu tệp bị thiếu, nó sẽ điều hướng toàn bộ trang đến một trang 404
Hugheth

7

Bạn có thể ẩn liên kết tải xuống và làm cho nút bấm vào nó.

<button onclick="document.getElementById('link').click()">Download!</button>
<a id="link" href="file.doc" download hidden></a>

Để điều này hoạt động trong Firefox, tài nguyên phải nằm trên cùng một miền với tài liệu. Đặt tiêu đề CORS không giúp được gì.
Antony

2
Đừng bao giờ làm điều này
Wannes

@Wannes tại sao không?
Starwarswii

4

Nếu bạn đang tìm kiếm một giải pháp JavaScript vanilla (không có jQuery) và không sử dụng thuộc tính HTML5, bạn có thể thử điều này.

const download = document.getElementById("fileRequest");

download.addEventListener('click', request);

function request() {
    window.location = 'document.docx';
}
.dwnld-cta {
    border-radius: 15px 15px;
    width: 100px;
    line-height: 22px
}
<h1>Download File</h1>
<button id="fileRequest" class="dwnld-cta">Download</button>


1

Đây là những gì cuối cùng đã làm việc cho tôi vì tệp được tải xuống được xác định khi trang được tải.

JS để cập nhật thuộc tính hành động của biểu mẫu:

function setFormAction() {
    document.getElementById("myDownloadButtonForm").action = //some code to get the filename;
}

Gọi JS để cập nhật thuộc tính hành động của biểu mẫu:

<body onLoad="setFormAction();">

Thẻ mẫu với nút gửi:

<form method="get" id="myDownloadButtonForm" action="">
    Click to open document:  
    <button type="submit">Open Document</button>
</form>

Những điều sau đây KHÔNG hoạt động:

<form method="get" id="myDownloadButtonForm" action="javascript:someFunctionToReturnFileName();">

có lẽ bởi vì nếu bạn có tệp khi tải, bạn không thể kết xuất hành động trên máy chủ bằng công cụ tạo khuôn mẫu? Tại sao cần mã js?
Andrei Epure

1

Nếu bạn không thể sử dụng biểu mẫu, một cách tiếp cận khác với downloadjs rất phù hợp. Downloadjs sử dụng API tệp blob và html 5 trong phần mềm:

{downloadjs (url, tên tệp)}) />

* đó là cú pháp jsx / React, nhưng có thể được sử dụng trong html thuần


Để tránh các sự cố CORS cho hình ảnh trên các miền khác, hãy đặt crossorigin = "nặc danh" vào thẻ img, như thế này: <img src = "image.png" crossorigin = "nặc danh" />
Jonathan Harris

0

Bất cứ nơi nào giữa thẻ <body></body>thẻ của bạn, hãy đặt một nút bằng mã dưới đây:

<button>
    <a href="file.doc" download>Click to Download!</a>
</button>

Điều này là chắc chắn để làm việc!


1
Đối với Chrome, đó là một giải pháp tuyệt vời
Hayk Aramyan

1
Không hoạt động trong Safari: Các trường W3
Alex

2
Không hoạt động trong trình duyệt MS là một vấn đề khá lớn và Chrome không phải lúc nào cũng là câu trả lời.
SudoKid

Bạn không thể đặt một liên kết bên trong một nút trong HTML
Quentin

0

Một cách khác để làm trong trường hợp bạn có một URL phức tạp, chẳng hạn như file.doc?foo=bar&jon=doethêm trường ẩn bên trong biểu mẫu

<form method="get" action="file.doc">
  <input type="hidden" name="foo" value="bar" />
  <input type="hidden" name="john" value="doe" />
  <button type="submit">Download Now</button>
</form>

lấy cảm hứng từ câu trả lời @Cfreak chưa hoàn thành


0

bạn có thể thêm thẻ mà không cần bất kỳ văn bản nào nhưng có liên kết. và khi bạn nhấp vào nút như bạn có trong mã, chỉ cần chạy hàm $ ("yourlink class"). click ().


-1

tải thuộc tính làm điều đó

 <a class="btn btn-success btn-sm" href="/file_path/file.type" download>
     <span>download </span>&nbsp;<i class="fa fa-download"></i>
 </a>

2
Tôi thích câu trả lời của bạn
George C.

2
Câu hỏi rõ ràng là hỏi làm thế nào để làm điều này với một nút thay vì một liên kết.
Quentin

-6

Nếu bạn sử dụng <a>thẻ, đừng quên sử dụng toàn bộ url dẫn đến tệp - tức là:

<a href="http://www.example.com/folder1/file.doc">Download</a>

Tôi không nghĩ đó là vấn đề ở đây. Ngoài ra, đường dẫn "tuyệt đối" không cần thiết nếu liên kết nằm trong cùng đường dẫn với tệp.
Tên lửa Hazmat

@Rocket - tất nhiên, bạn đúng về con đường tuyệt đối, tuy nhiên, đó là cách tốt nhất để đảm bảo làm cho đúng. Tôi sẽ để nó cho OP để quyết định xem nó có hữu ích không -
Đánh dấu

Câu hỏi rõ ràng là hỏi làm thế nào để làm điều này với một nút thay vì một liên kết.
Quentin

thuộc tính tải xuống bị thiếu trong giải pháp này. Ngay cả sau khi thêm thuộc tính tải xuống, nó sẽ không hoạt động cho tên miền chéo.
s sharif

-6

Đối với tôi nút ading thay vì neo văn bản hoạt động thực sự tốt.

<a href="file.doc"><button>Download!</button></a>

Nó có thể không ổn theo hầu hết các quy tắc, nhưng nó có vẻ khá tốt.


5
Điều này chỉ hoạt động vì trình duyệt của bạn không hỗ trợ các tệp .doc.
Thiết kế của Adrian

HTML của bạn không hợp lệ. <a>các phần tử có thể không chứa <button>các phần tử.
Quentin

luôn luôn là như vậy? Câu trả lời này đã được hai tuổi khi bạn nhận xét rằng.
John Lord
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.