একটি এজ্যাক্স অনুরোধ ব্যবহার করে ফাইল ডাউনলোড করুন


96

আমি যখন একটি বোতামে ক্লিক করি তখন "এজাক্স ডাউনলোডের অনুরোধ" পাঠাতে চাই, তাই আমি এইভাবে চেষ্টা করেছি:

জাভাস্ক্রিপ্ট:

var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();

ডাউনলোড.এফপি:

<?
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= file.txt");
header("Content-Transfer-Encoding: binary");    
readfile("file.txt");
?>

তবে প্রত্যাশার মতো কাজ করে না, কীভাবে করব? তুমাকে অগ্রিম ধন্যবাদ


4
এটি কার্যকর হবে না, [এই প্রশ্ন] [1] দেখুন। [1]: stackoverflow.com/questions/8771342/...
olegsv

4
করlocation.href='download.php';
মুসা

এই চেষ্টা stackoverflow.com/a/42235655/2282880
Meloman

উত্তর:


94

27 এপ্রিল, 2015 আপডেট করুন

এইচটিএমএল 5 দৃশ্যে এসে উপস্থিতি হ'ল ডাউনলোড বৈশিষ্ট্য । এটি ফায়ারফক্স এবং ক্রোমে সমর্থিত এবং শীঘ্রই আইই 11 এ আসবে। আপনার প্রয়োজনের উপর নির্ভর করে আপনি window.locationএতক্ষণ এজেএক্স অনুরোধের (বা ব্যবহারের ) পরিবর্তে এটি ব্যবহার করতে পারবেন যতক্ষণ আপনি ডাউনলোড করতে চান ফাইলটি আপনার সাইটের অনুরূপ উত্সতে থাকে।

আপনি সর্বদা AJAX অনুরোধ / window.locationএকটি জাল স্ক্রিপ্ট ব্যবহার করে কিছুdownload সমর্থন করে কিনা তা পরীক্ষার জন্য এবং যদি কল না করে তা পরিবর্তন করে তা পরীক্ষা করতে পারেন window.location

আসল উত্তর

ডাউনলোডের প্রম্পটটি খোলার জন্য আপনার কাছে একটি এজেএক্স অনুরোধ থাকতে পারে না কারণ আপনার শারীরিকভাবে ডাউনলোডের জন্য প্রম্পটে ফাইলটিতে নেভিগেট করতে হবে। পরিবর্তে, আপনি download.php নেভিগেট করতে একটি সাফল্য ফাংশন ব্যবহার করতে পারেন। এটি ডাউনলোড প্রম্পটটি খুলবে তবে বর্তমান পৃষ্ঠাটি পরিবর্তন করবে না।

$.ajax({
    url: 'download.php',
    type: 'POST',
    success: function() {
        window.location = 'download.php';
    }
});

যদিও এটি প্রশ্নের উত্তর দেয়, কেবলমাত্র window.locationএজেএক্স অনুরোধটিকে পুরোপুরি ব্যবহার করা এবং এড়ানো ভাল better


39
এই লিঙ্কটি দুইবার কল না? আমি একই ধরণের নৌকায় আছি ... আমি হেডারে প্রচুর সুরক্ষা তথ্য পার করছি, এবং সাফল্যের ফাংশনে ফাইলের বিষয়বস্তু বিশ্লেষণ করতে সক্ষম, তবে ডাউনলোড প্রম্পটটি কীভাবে ট্রিগার করতে হয় তা জানি না।
ব্যবহারকারী 1447679

4
এটি পৃষ্ঠাটিতে দু'বার কল করবে, সুতরাং আপনি যদি সেই পৃষ্ঠাটিতে একটি ডাটাবেস অনুসন্ধান করছেন, এর অর্থ ডিবিতে 2 টি ট্রিপ।
মিমি মিমি মিমি

4
@ user1447679 একটি বিকল্প সমাধান জন্য দেখুন: stackoverflow.com/questions/38665947/...
জন

4
আমাকে কীভাবে এটি সাহায্য করেছে তা আমাকে ব্যাখ্যা করুন ... উদাহরণটি আরও সম্পূর্ণ হতে পারে। "download.php? get_file = সত্য" বা অন্য কিছু দিয়ে ... আমার একটি এজাক্স ফাংশন রয়েছে যা ফর্ম জমা দেওয়ার সময় কিছুটা ত্রুটি করে এবং তারপরে একটি সিএসভি ফাইল তৈরি করে। যদি ত্রুটি চেকটি ব্যর্থ হয় তবে এটি কেন ব্যর্থ হয়েছিল তা নিয়ে ফিরে আসতে হবে। যদি এটি সিএসভি তৈরি করে তবে এটি পিতামাতাকে বলছে "এগিয়ে যান এবং ফাইলটি আনুন"। আমি ফর্ম ভেরিয়েবলের সাথে এজাক্স ফাইলে পোস্ট করে একই ফাইলটিতে একটি "ডিফারেন্ট প্যারামিটার" পোস্ট করে বলছি "আপনি সদ্য তৈরি করা ফাইলটি আমাকে হস্ত করুন" (পাথ / নামটি এজ্যাক্স ফাইলটিতে হার্ড কোডিং করা হয়েছে)।
স্কট

4
তবে এটি 2 বার অনুরোধ পাঠাবে, এটি যথাযথ নয়
ধর্মেন্দ্রসিংহ চুদসামা

45

ব্রাউজারটি কোনও ফাইল ডাউনলোড করতে আপনার অনুরোধটি তৈরি করতে হবে:

 function downloadFile(urlToSend) {
     var req = new XMLHttpRequest();
     req.open("GET", urlToSend, true);
     req.responseType = "blob";
     req.onload = function (event) {
         var blob = req.response;
         var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
         var link=document.createElement('a');
         link.href=window.URL.createObjectURL(blob);
         link.download=fileName;
         link.click();
     };

     req.send();
 }

7
এটি আমার পক্ষে কাজ করে তবে ফায়ারফক্সে ফাইলটি স্বয়ংক্রিয়ভাবে ডাউনলোড করার জন্য আমাকে প্রথমে ডিওমে একটি <a> ট্যাগ লাগাতে হবে এবং এটিকে আমার লিঙ্ক হিসাবে উল্লেখ করতে হবে।
এরিক ডোনহু

কাজ করে তবে এক্সিকিউশন চলাকালীন যদি ফাইলটি তৈরি হয় তবে কী হবে? ফাইলটি ইতিমধ্যে তৈরি হওয়ার সময় এটি কাজ করে না।
দিয়েগো

@ তাহা আমি এজতে এটি পরীক্ষা করেছি এবং দেখে মনে হচ্ছে এটি কার্যকর হবে। আই আই সম্পর্কে জানেন না যদিও। আমার ক্লায়েন্ট IE ব্যবহারকারীদের লক্ষ্য করে না ;-) আমি কি ভাগ্যবান? : ডি
এস

4
@ এরিকডোনহু আপনি <a>জেএস-এর সাথে ট্যাগ করতে পারবেন "উড়ানের দিকে", তবে এতে যোগ করতে হবে document.body। আপনি অবশ্যই এটি একই সময়ে আড়াল করতে চান।
মার্টন ট্যামস

ধন্যবাদ @ জোওো, আমি দীর্ঘদিন থেকে এই সমাধানটির সন্ধান করছিলাম।
অভিষেক ঘরই

44

এটির জন্য আসলে আপনার এজাক্সের মোটেই দরকার নেই। আপনি যদি কেবল "ডাউনলোড.php" টি বোতামের href হিসাবে সেট করেন, বা, যদি এটি কোনও লিঙ্ক ব্যবহার না করে:

window.location = 'download.php';

ব্রাউজারটি বাইনারি ডাউনলোডকে স্বীকৃতি দেয় এবং প্রকৃত পৃষ্ঠাটি লোড না করে কেবল ফাইলটিকে ডাউনলোড হিসাবে পরিবেশন করে।


4
আপনি যে প্রোগ্রামিং ভাষাটি পরিবর্তন করতে ব্যবহার করছেন তা window.location হ'ল জাভাস্ক্রিপ্ট।
মাইকমেকানা

4
আপনি ঠিক বলেছেন @ মিমিকম্যাকানা, আমি আসলে এজাক্স :) বলতে চাইছিলাম।
জেলি ক্রাল্ট

4
একটি সমাধানের জন্য উচ্চ এবং নিম্ন শিকার করেছেন এবং এটি এত মার্জিত এবং নিখুঁত। তোমাকে অনেক ধন্যবাদ.
ইয়াংশুন তাই

4
অবশ্যই, এই সমাধানটি কেবল তখনই কাজ করবে যদি এটি একটি স্ট্যাটিক ফাইল যা ইতিমধ্যে বিদ্যমান।
ক্রিলগার

4
সার্ভারটি যদি কোনও ত্রুটির সাথে প্রতিক্রিয়া জানায় তবে ব্রাউজারের দ্বারা ত্রুটি পৃষ্ঠায় পুনর্নির্দেশ না করে আপনার মূল পৃষ্ঠায় থাকার কোনও উপায় থাকবে না। উইন্ডো.লোকেশনের ফলাফল 404 ফেরত যাওয়ার সময় ক্রোম কমপক্ষে এটি করে
ইয়ান

21

ক্রস ব্রাউজার সমাধান, ক্রোম, ফায়ারফক্স, এজ, আইই 11 এ পরীক্ষিত।

ডোমে, একটি লুকানো লিঙ্ক ট্যাগ যুক্ত করুন:

<a id="target" style="display: none"></a>

তারপরে:

var req = new XMLHttpRequest();
req.open("GET", downloadUrl, true);
req.responseType = "blob";
req.setRequestHeader('my-custom-header', 'custom-value'); // adding some headers (if needed)

req.onload = function (event) {
  var blob = req.response;
  var fileName = null;
  var contentType = req.getResponseHeader("content-type");

  // IE/EDGE seems not returning some response header
  if (req.getResponseHeader("content-disposition")) {
    var contentDisposition = req.getResponseHeader("content-disposition");
    fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
  } else {
    fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
  }

  if (window.navigator.msSaveOrOpenBlob) {
    // Internet Explorer
    window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
  } else {
    var el = document.getElementById("target");
    el.href = window.URL.createObjectURL(blob);
    el.download = fileName;
    el.click();
  }
};
req.send();

ভাল জেনেরিক কোড। @ লেও আপনি কি পছন্দসই শিরোনামের মতো এই কোডটি উন্নত করতে পারেন Authorization?
vibs2006

4
ধন্যবাদ @ লিও। এটি সহায়ক A এছাড়াও window.URL.revokeObjectURL(el.href);পরে আপনি কী যুক্ত করার পরামর্শ দিচ্ছেন el.click()?
vis2006

ফাইলের নামটি ভুল হবে যদি বিষয়বস্তু প্রদর্শন কোনও ইউটিএফ 8 নন ফাইলের নাম নির্দিষ্ট করে।
ম্যাথিউ অ্যালডেন

14

এটা সম্ভব. আপনি একটি আজাক্স ফাংশনটির ভিতরে থেকে ডাউনলোড শুরু করতে পারেন, উদাহরণস্বরূপ, .csv ফাইলটি তৈরি হওয়ার ঠিক পরে।

আমার একটি এজাক্স ফাংশন রয়েছে যা একটি .csv ফাইলে পরিচিতিগুলির একটি ডাটাবেস রপ্তানি করে এবং এটি শেষ হওয়ার পরে এটি স্বয়ংক্রিয়ভাবে .csv ফাইল ডাউনলোড শুরু করে। সুতরাং, আমি প্রতিক্রিয়াটি পাওয়ার পরে এবং সবকিছু ঠিকঠাক পরে, আমি ব্রাউজারটিকে পুনঃনির্দেশ করি:

window.location="download.php?filename=export.csv";

আমার ডাউনলোড.এফপি ফাইলটি দেখতে এমন দেখাচ্ছে:

<?php

    $file = $_GET['filename'];

    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Disposition: attachment; filename=".$file."");
    header("Content-Transfer-Encoding: binary");
    header("Content-Type: binary/octet-stream");
    readfile($file);

?>

কোনও পৃষ্ঠা রিফ্রেশ নেই এবং ফাইলটি স্বয়ংক্রিয়ভাবে ডাউনলোড শুরু হয়।

দ্রষ্টব্য - নিম্নলিখিত ব্রাউজারগুলিতে পরীক্ষিত:

Chrome v37.0.2062.120 
Firefox v32.0.1
Opera v12.17
Internet Explorer v11

4
এই বিপজ্জনক নিরাপত্তা অনুযায়ী নয়?
মিকেল বার্গারন ন্যারন

@ মিকেলবার্গারন নরন কেন?
পেড্রো সওসা

4
আমি তাই ভাবব কারণ যে কেউ ডাউনলোড.এফপি? ফাইল নাম = [কিছু] কল করতে পারে এবং কিছু পথ এবং ফাইলের নাম, বিশেষত সাধারণগুলি চেষ্টা করতে পারে এবং এটি এমনকি কোনও প্রোগ্রাম বা স্ক্রিপ্টের মধ্যে একটি লুপের মধ্যেও করা যেতে পারে।
মিকেল বার্গারন ন্যারন

না। htaccess যে এড়ানো?
পেড্রো সওসা

9
@ পেড্রোসোসা .. না। htaccess অ্যাপাচি মাধ্যমে ফাইল কাঠামো অ্যাক্সেস নিয়ন্ত্রণ করে। অ্যাক্সেস যেহেতু কোনও পিএইচপি স্ক্রিপ্টে পৌঁছেছে, এইচটিএইচসেস এখন তার দায়িত্ব বন্ধ করে দেয়। এটি একটি সুরক্ষা গর্ত খুব বেশি কারণ প্রকৃতপক্ষে, পিএইচপি (এবং এটির অধীনে চলমান ব্যবহারকারী) যে কোনও ফাইল পড়তে পারে, তাই এটি পঠন ফাইলে পৌঁছে দিতে পারে ... অনুরোধ করা ফাইলটি পড়ার জন্য সর্বদা স্যানিটাইজ করা উচিত
অধ্যাপক


0

শিরোনাম থেকে একটি ফাইলের নাম ডিকোড করা কিছুটা জটিল ...

    var filename = "default.pdf";
    var disposition = req.getResponseHeader('Content-Disposition');

    if (disposition && disposition.indexOf('attachment') !== -1) 
    {
       var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
       var matches = filenameRegex.exec(disposition);

       if (matches != null && matches[1]) 
           filename = matches[1].replace(/['"]/g, '');
    }

4
আপনার পুরো কোড ব্লকটি ফর্ম্যাট করুন এবং ভবিষ্যতের পাঠক সুবিধার জন্য আপনার প্রক্রিয়াটির জন্য কিছু অতিরিক্ত ব্যাখ্যা সরবরাহ করুন।
মিকম্যাকুসা

0

এই সমাধানটি উপরেরগুলির থেকে খুব আলাদা নয়, তবে আমার জন্য এটি খুব ভালভাবে কাজ করে এবং আমি মনে করি এটি পরিষ্কার।

আমি বেস সার্ভারের পাশটি বেস 64 কে এনকোড করার প্রস্তাব দিচ্ছি (বেস64_ইনকোড (), আপনি যদি পিএইচপি ব্যবহার করেন) এবং ক্লায়েন্টকে বেস 64 এনকোডড ডেটা প্রেরণ করুন

ক্লায়েন্টের উপর আপনি এটি করেন:

 let blob = this.dataURItoBlob(THE_MIME_TYPE + "," + response.file);
 let uri = URL.createObjectURL(blob);
 let link = document.createElement("a");
 link.download = THE_FILE_NAME,
 link.href = uri;
 document.body.appendChild(link);
 link.click();
 document.body.removeChild(link);

এই কোডটি একটি লিঙ্কে এনকোডড ডেটা রাখে এবং লিঙ্কটিতে একটি ক্লিক সিমুলেট করে, তারপরে এটি এটিকে সরিয়ে দেয়।


আপনি কেবল ট্যাগটি গোপন করতে পারেন এবং গতিময়ভাবে href তৈরি করতে পারেন। যোগ এবং অপসারণ করার দরকার নেই
বিপিইলা

0

আপনার প্রয়োজনীয়তাগুলি কভার করা হয়েছে window.location('download.php');
তবে আমি মনে করি যে আপনাকে ডাউনলোড করার জন্য ফাইলটি পাস করতে হবে, সর্বদা একই ফাইলটি ডাউনলোড করা উচিত নয় এবং এজন্য আপনি একটি অনুরোধ ব্যবহার করছেন, একটি বিকল্প হ'ল পিএইচপি ফাইলটি শোফাইল.এফপি হিসাবে সহজ হিসাবে তৈরি করা এবং অনুরোধ করুন

var myfile = filetodownload.txt
var url = "shofile.php?file=" + myfile ;
ajaxRequest.open("GET", url, true);

showfile.php

<?php
$file = $_GET["file"] 
echo $file;

যেখানে ফাইলটি ফাইলের নাম হিসাবে অনুরোধে গেট বা পোস্টের মাধ্যমে পাস হয় এবং তারপরে কোনও কার্যক্রমে প্রতিক্রিয়াটি কেবল ধরা দেয়

if(ajaxRequest.readyState == 4){
                        var file = ajaxRequest.responseText;
                        window.location = 'downfile.php?file=' + file;  
                    }
                }

0

এজ্যাক্সে ওয়েব পৃষ্ঠা ডাউনলোড করার জন্য আরও একটি সমাধান রয়েছে। তবে আমি এমন একটি পৃষ্ঠা উল্লেখ করছি যা প্রথমে প্রক্রিয়া করা হবে এবং তারপরে ডাউনলোড করতে হবে।

প্রথমে আপনাকে ফলাফল ডাউনলোড থেকে পৃষ্ঠা প্রসেসিং আলাদা করতে হবে।

1) কেবলমাত্র পাতার গণনাগুলি আজাক্স কলে করা হয়।

p .পোস্ট ("ক্যালকুলাসপেজ.এফপি", {ক্যালকুলাস ফাংশন: সত্য, আইডি: 29, ডেটা 1: "এ", ডেটা 2: "বি"},

       ফাংশন (তথ্য, স্থিতি) 
       {
            যদি (স্থিতি == "সাফল্য") 
            {
                / * 2) উত্তরে পূর্বের গণনাগুলি ব্যবহার করে যে পৃষ্ঠাটি ডাউনলোড করা হবে। উদাহরণস্বরূপ, এটি এমন একটি পৃষ্ঠা হতে পারে যা আজাক্স কলে গণনা করা একটি সারণির ফলাফলগুলি মুদ্রণ করে। * /
                window.location.href = DownloadPage.php + "? ID =" + 29;
            }               
       }
);

// উদাহরণস্বরূপ: ক্যালকুলাসপেজ.এফপি

    যদি (! খালি ($ _ পোষ্ট ["ক্যালকুলাস ফাংশন"])) 
    {
        $ আইডি = $ _POST ["আইডি"];

        $ ক্যোয়ারী = "উদাহরণ পৃষ্ঠায় অন্তর্ভুক্ত করুন (ডেটা 1, ডেটা 2) ভ্যালু ('"। P _ পোস্ট ["ডেটা 1"]। "', '"। P _ পোস্ট ["ডেটা 2"]। "') আইডি;" "$ আইডি;
        ...
    }

// উদাহরণস্বরূপ: DownloadPage.php এ

    $ ID = $ _GET ["আইডি"];

    ede sede = "উদাহরণ পেজ থেকে নির্বাচন করুন * যেখানে আইডি =" $ আইডি;
    ...

    $ ফাইলের নাম = "এক্সপোর্ট_ডাটা.এক্সলস";
    শিরোনাম ("বিষয়বস্তুর ধরণ: অ্যাপ্লিকেশন / vnd.ms-Excel");
    শিরোনাম ("বিষয়বস্তু-বিভাজন: ইনলাইন; ফাইলের নাম = $ ফাইলের নাম");

    ...

আমি আশা করি এই সমাধানটি অনেকের পক্ষে কার্যকর হতে পারে, যেমনটি আমার জন্য ছিল।


0

যারা আরও আধুনিক পদ্ধতির সন্ধান করছেন তাদের জন্য আপনি এটি ব্যবহার করতে পারেন fetch API। নীচের উদাহরণে স্প্রেডশিট ফাইলটি কীভাবে ডাউনলোড করবেন তা দেখানো হয়েছে। এটি নিম্নলিখিত কোড সহ সহজেই সম্পন্ন হয়।

fetch(url, {
    body: JSON.stringify(data),
    method: 'POST',
    headers: {
        'Content-Type': 'application/json; charset=utf-8'
    },
})
.then(response => response.blob())
.then(response => {
    const blob = new Blob([response], {type: 'application/application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
    const downloadUrl = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = downloadUrl;
    a.download = "file.xlsx";
    document.body.appendChild(a);
    a.click();
})

আমি বিশ্বাস করি যে এই XMLHttpRequestসমাধানটি অন্যান্য সমাধানের চেয়ে বোঝা সহজ । এছাড়াও, এটির সাথে jQueryবাড়তি কোনও লাইব্রেরি যুক্ত করার প্রয়োজন ছাড়াই এই পদ্ধতির অনুরূপ বাক্য গঠন রয়েছে ।

অবশ্যই, আপনি কোন ব্রাউজারটি বিকাশ করছেন তা যাচাই করার পরামর্শ দেব, যেহেতু এই নতুন পদ্ধতির আইই তে কাজ করবে না। আপনি নিম্নলিখিত লিঙ্কে সম্পূর্ণ ব্রাউজারের সামঞ্জস্যের তালিকাটি পেতে পারেন ।

গুরুত্বপূর্ণ : এই উদাহরণে আমি প্রদত্ত একটি শোনার সার্ভারে একটি JSON অনুরোধ পাঠাচ্ছি url। এটি urlঅবশ্যই সেট করা উচিত, আমার উদাহরণে আমি ধরে নিচ্ছি যে আপনি এই অংশটি জানেন। এছাড়াও, আপনার অনুরোধটি কাজ করার জন্য প্রয়োজনীয় শিরোনামগুলি বিবেচনা করুন। যেহেতু আমি একটি JSON- পাঠাচ্ছি, আমি যোগ করা আবশ্যক Content-Typeহেডার এবং এটি সেট application/json; charset=utf-8, যেমন সার্ভারটি অনুরোধটি এটা পাবেন ধরণ জানাতে।


0

@ জোয়াও মার্কোস সলিউশনটি আমার পক্ষে কাজ করে তবে কোডটি দেখতে দেখতে যদি নীচে থাকে তবে নীচে কোডটি আইইতে কাজ করার জন্য কোডটি পরিবর্তন করতে হয়েছিল

       downloadFile(url,filename) {
        var that = this;
        const extension =  url.split('/').pop().split('?')[0].split('.').pop();

        var req = new XMLHttpRequest();
        req.open("GET", url, true);
        req.responseType = "blob";
        req.onload = function (event) {
            const fileName = `${filename}.${extension}`;
            const blob = req.response;

            if (window.navigator.msSaveBlob) { // IE
                window.navigator.msSaveOrOpenBlob(blob, fileName);
            } 
            const link = document.createElement('a');
            link.href = window.URL.createObjectURL(blob);                
            link.download = fileName;
            link.click();
            URL.revokeObjectURL(link.href);

        };

        req.send();
    },
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.