2011-07-12 4 views
29

Tôi có một nút và onclick nó sẽ gọi một hàm ajax.Tải tập tin qua một cuộc gọi ajax php

Đây là chức năng ajax tôi

function csv(){ 

    ajaxRequest = ajax();//ajax() is function that has all the XML HTTP Requests 

    postdata = "data=" + document.getElementById("id").value; 

    ajaxRequest.onreadystatechange = function(){ 
     var ajaxDisplay = document.getElementById('ajaxDiv'); 
     if(ajaxRequest.readyState == 4 && ajaxRequest.status==200){ 
      ajaxDisplay.innerHTML = ajaxRequest.responseText;   
     } 
    } 

    ajaxRequest.open("POST","csv.php",false); 
    ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
    ajaxRequest.send(postdata); 
} 

tôi tạo ra các tập tin csv dựa trên đầu vào người dùng. Sau khi nó được tạo ra tôi muốn nó để tải về tải về hoặc lực lượng tải về (tốt nhất là lực lượng). Tôi đang sử dụng tập lệnh sau ở cuối tệp php để tải xuống tệp. Nếu tôi chạy tập lệnh này trong một tệp riêng biệt thì nó hoạt động tốt.

$fileName = 'file.csv'; 
$downloadFileName = 'newfile.csv'; 

if (file_exists($fileName)) { 
    header('Content-Description: File Transfer'); 
    header('Content-Type: text/csv'); 
    header('Content-Disposition: attachment; filename='.$downloadFileName); 
    ob_clean(); 
    flush(); 
    readfile($fileName); 
    exit; 
} 
echo "done"; 

Nhưng nếu tôi chạy nó vào cuối csv.php, nó sẽ xuất nội dung của tệp.csv vào trang (vào ajaxDiv) thay vì tải xuống.

Có cách nào để buộc tải xuống tệp ở cuối csv.php không?

Trả lời

36

AJAX không phải để tải xuống tệp. Bật cửa sổ mới với liên kết tải xuống làm địa chỉ của cửa sổ hoặc làm document.location = ....

+16

Tôi tin rằng về mặt kỹ thuật nó tốt hơn để thiết lập 'window.location'; xem thảo luận này: http://stackoverflow.com/questions/7857878/window-location-vs-document-location – yitwail

8

Tôi đã thực hiện điều này bằng iframe ẩn. Tôi sử dụng perl, không phải php, vì vậy sẽ chỉ cung cấp cho khái niệm, không giải pháp mã.

Máy khách gửi yêu cầu Ajax tới máy chủ, khiến nội dung tệp được tạo. Điều này được lưu dưới dạng tệp tạm thời trên máy chủ và tên tệp được trả lại cho máy khách.

Khách hàng (javascript) nhận tên tập tin và thiết lập src iframe để một số url mà sẽ cung cấp các tập tin, như:

$('iframe_dl').src="/app?download=1&filename=" + the_filename 

server slurps tập tin, hủy liên kết nó, và gửi dòng cho khách hàng, với các tiêu đề này:

Content-Type:'application/force-download' 
Content-Disposition:'attachment; filename=the_filename' 

Hoạt động như một sự quyến rũ.

8

@joe: Rất cám ơn, đây là một người đứng đầu tốt!

Tôi đã có một vấn đề hơi khó khăn hơn: 1. gửi một yêu cầu với dữ liệu POST AJAX, cho máy chủ để tạo ra một tập tin ZIP 2. nhận được phản hồi trở lại 3. tải về các tập tin ZIP

Vì vậy, đó là làm thế nào tôi đã làm nó (sử dụng JQuery để xử lý các yêu cầu AJAX):

  1. bài ban đầu yêu cầu:

    var parameters = { 
        pid  : "mypid", 
        "files[]": ["file1.jpg","file2.jpg","file3.jpg"] 
    }

    var options = { url: "request/url",//replace with your request url type: "POST",//replace with your request type data: parameters,//see above context: document.body,//replace with your contex success: function(data){ if (data) { if (data.path) { //Create an hidden iframe, with the 'src' attribute set to the created ZIP file. var dlif = $('<iframe/>',{'src':data.path}).hide(); //Append the iFrame to the context this.append(dlif); } else if (data.error) { alert(data.error); } else { alert('Something went wrong'); } } } }; $.ajax(options);

"Yêu cầu/url" xử lý việc tạo zip (tắt chủ đề, vì vậy tôi sẽ không đăng toàn bộ mã) và trả về đối tượng JSON sau.Một cái gì đó như:

//Code to create the zip file 
//...... 
//Id of the file 
$zipid = "myzipfile.zip" 
//Download Link - it can be prettier 
$dlink = 'http://'.$_SERVER["SERVER_NAME"].'/request/download&file='.$zipid; 
//JSON response to be handled on the client side 
$result = '{"success":1,"path":"'.$dlink.'","error":null}'; 
header('Content-type: application/json;'); 
echo $result; 

"yêu cầu/tải" có thể thực hiện một số kiểm tra an ninh, nếu cần thiết, và tạo ra các tập tin chuyển giao:

$fn = $_GET['file']; 
if ($fn) { 
    //Perform security checks 
    //.....check user session/role/whatever 
    $result = $_SERVER['DOCUMENT_ROOT'].'/path/to/file/'.$fn; 
    if (file_exists($result)) { 
    header('Content-Description: File Transfer'); 
    header('Content-Type: application/force-download'); 
    header('Content-Disposition: attachment; filename='.basename($result)); 
    header('Content-Transfer-Encoding: binary'); 
    header('Expires: 0'); 
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); 
    header('Pragma: public'); 
    header('Content-Length: ' . filesize($result)); 
    ob_clean(); 
    flush(); 
    readfile($result); 
    @unlink($result); 
    } 

} 
+0

Chỉ cần & cần thay đổi thành? cho chuỗi truy vấn. Cảm ơn sự giúp đỡ tuyệt vời với điều này mặc dù! - Tôi đã cố gắng để làm một chỉnh sửa nhưng nó là một nhỏ như vậy nó sẽ không cho tôi !! $ dlink = 'http: //'.$_SERVER ["SERVER_NAME"].'/Request/download? File = '. $ Zipid; –

19

Một giải pháp rất đơn giản sử dụng jQuery:

trên phía khách hàng:

$('.act_download_statement').click(function(e){ 
    e.preventDefault(); 
    form = $('#my_form'); 
    form.submit(); 
}); 

và ở phía máy chủ, đảm bảo bạn gửi lại chính xác Content-Type tiêu đề, do đó trình duyệt sẽ biết tệp đính kèm của nó và quá trình tải xuống sẽ bắt đầu.

+1

+1 Điều này làm việc tuyệt vời cho tôi khi POST dữ liệu lên máy chủ và tải xuống tệp ZIP dưới dạng phản hồi. Không tải lại trang. –

+0

+1 Bài đăng kỹ thuật hơn và là một mẹo hay – bizzr3

+0

Bạn có thể cung cấp thêm một chút chi tiết và cung cấp một số mã về điều gì xảy ra ở cả hai đầu không? –

2

Bạn không thể tải trực tiếp tệp xuống qua ajax.

Bạn có thể đặt liên kết trên trang có URL tới tệp của bạn (được trả về từ cuộc gọi ajax) hoặc cách khác là sử dụng dấu bị ẩn iframe và đặt URL của nguồn đó iframe động. Bằng cách này bạn có thể tải xuống tệp mà không cần làm mới trang.

Đây là mã

$.ajax({ 
    url : "yourURL.php", 
    type : "GET", 
    success : function(data) { 
     $("#iframeID").attr('src', 'downloadFileURL'); 
    } 
}); 
+0

Đăng mã có liên quan sẽ giúp minh họa những gì bạn đang cố gắng nói ở đây. – larsAnders

+0

trên phản hồi thành công ajax của bạn, bạn có thể đặt iframe ẩn src –