JSON ডেটা সহ পোষ্টের মাধ্যমে ফাইল ডাউনলোড করতে জাভাস্ক্রিপ্ট / jQuery


250

আমার কাছে একটি jquery- ভিত্তিক একক পৃষ্ঠার ওয়েবঅ্যাপ রয়েছে। এটি এজেএক্স কলগুলির মাধ্যমে একটি রেস্টস্টুল ওয়েব সার্ভিসের সাথে যোগাযোগ করে।

আমি নিম্নলিখিতগুলি সম্পাদন করার চেষ্টা করছি:

  1. একটি POST জমা দিন যাতে একটি REST url এ JSON ডেটা রয়েছে।
  2. যদি অনুরোধটি কোনও JSON প্রতিক্রিয়া নির্দিষ্ট করে, তবে জেএসএন ফিরে আসবে।
  3. যদি অনুরোধটি একটি পিডিএফ / এক্সএলএস / ইত্যাদি প্রতিক্রিয়া নির্দিষ্ট করে, তবে একটি ডাউনলোডযোগ্য বাইনারি ফিরে আসে।

আমার এখন 1 & 2 কাজ করছে এবং ক্লায়েন্ট jquery অ্যাপ্লিকেশনটি JSON ডেটার ভিত্তিতে DOM উপাদান তৈরি করে ওয়েব পৃষ্ঠায় ফিরে আসা ডেটা প্রদর্শন করে। ওয়েব-সার্ভিস দৃষ্টিকোণ থেকে আমার কাছে # 3 কাজ করছে, এর অর্থ এটি যদি সঠিক JSON পরামিতি দেওয়া হয় তবে এটি একটি বাইনারি ফাইল তৈরি এবং ফিরিয়ে আনবে। তবে আমি ক্লায়েন্ট জাভাস্ক্রিপ্ট কোডে # 3 সাথে ডিল করার সর্বোত্তম উপায় সম্পর্কে নিশ্চিত নই।

এইভাবে একটি অজ্যাক্স কল থেকে কোনও ডাউনলোডযোগ্য ফাইল ফিরে পাওয়া সম্ভব? ফাইলটি ডাউনলোড এবং সংরক্ষণ করার জন্য ব্রাউজারটি কীভাবে পাব?

$.ajax({
    type: "POST",
    url: "/services/test",
    contentType: "application/json",
    data: JSON.stringify({category: 42, sort: 3, type: "pdf"}),
    dataType: "json",
    success: function(json, status){
        if (status != "success") {
            log("Error loading data");
            return;
        }
        log("Data loaded!");
    },
    error: function(result, status, err) {
        log("Error loading data");
        return;
    }
});

সার্ভারটি নিম্নলিখিত শিরোনামগুলির সাথে প্রতিক্রিয়া জানায়:

Content-Disposition:attachment; filename=export-1282022272283.pdf
Content-Length:5120
Content-Type:application/pdf
Server:Jetty(6.1.11)

আর একটি ধারণা হ'ল পিডিএফ তৈরি করা এবং এটি সার্ভারে সঞ্চয় করা এবং জেএসওএন ফিরিয়ে দেওয়া যাতে ফাইলটিতে একটি URL অন্তর্ভুক্ত থাকে includes তারপরে, এজ্যাক্স সাফল্যের হ্যান্ডেলারটিতে নীচের মতো কিছু করার জন্য আর একটি কল জারি করুন:

success: function(json,status) {
    window.location.href = json.url;
}

তবে তার মানে হল সার্ভারে আমার একাধিক কল করা দরকার এবং আমার সার্ভারে ডাউনলোডযোগ্য ফাইলগুলি তৈরি করতে হবে, সেগুলি কোথাও সংরক্ষণ করতে হবে এবং পরে পর্যায়ক্রমে সেই সঞ্চয় স্থানটি পরিষ্কার করতে হবে।

এটি সম্পাদন করার জন্য অবশ্যই একটি সহজ উপায় থাকতে হবে। ধারনা?


সম্পাদনা: aj .জ্যাক্সের জন্য দস্তাবেজগুলি পর্যালোচনা করার পরে, আমি দেখতে পাচ্ছি যে প্রতিক্রিয়া ডেটা টাইপ কেবলমাত্র একটি হতে পারে xml, html, script, json, jsonp, text, তাই আমি অনুমান করছি যে কোনও বাইনারি ফাইল এম্বেড না করে অ্যাজাক্স অনুরোধ ব্যবহার করে সরাসরি কোনও ফাইল ডাউনলোড করার উপায় নেই is @ উইনাইসি উত্তরে প্রস্তাবিত ডেটা ইউআরআই স্কিম (যা আমি কিছু করতে চাই না)।

সুতরাং আমি অনুমান করি আমার বিকল্পগুলি হ'ল:

  1. এজ্যাক্স ব্যবহার করবেন না এবং পরিবর্তে একটি ফর্ম পোস্ট জমা দিন এবং আমার JSON ডেটা ফর্মের মানগুলিতে এম্বেড করুন। লুকিয়ে থাকা আইফ্রেমেস এবং এই জাতীয়গুলির সাথে সম্ভবত গণ্ডগোলের প্রয়োজন হবে।

  2. এজাক্স ব্যবহার করবেন না এবং এর পরিবর্তে আমার জেএসওএন ডেটাটিকে একটি জিআরআর অনুরোধ তৈরি করতে ও একটি ইউআরএল-এ Windows.location.href সেট করার জন্য কোয়েরি স্ট্রিংয়ে রূপান্তর করুন। অ্যাপ্লিকেশন ইউআরএল থেকে ব্রাউজারটি পরিবর্তন থেকে রক্ষা করতে আমার ক্লিক হ্যান্ডলারে ইভেন্ট.প্রিভেন্টডেফল্ট () ব্যবহার করার প্রয়োজন হতে পারে।

  3. উপরের আমার অন্যান্য ধারণাটি ব্যবহার করুন তবে @naikus উত্তরের পরামর্শ দিয়ে বর্ধিত করেছেন। এমন কিছু প্যারামিটারের সাথে AJAX অনুরোধ জমা দিন যা ওয়েব-পরিষেবাটি জানতে দেয় যে এটি একটি এজাক্স কলের মাধ্যমে আহ্বান করা হচ্ছে। যদি অজ্যাক্স কল থেকে ওয়েব পরিষেবাটি কল করা হয় তবে উত্পন্ন উত্সটিতে কেবল একটি URL সহ জেএসএনকে ফিরিয়ে দিন। যদি উত্সটি সরাসরি ডাকা হয়, তবে আসল বাইনারি ফাইলটি ফিরিয়ে দিন।

আমি এটি সম্পর্কে যত বেশি চিন্তা করি, ততই আমি শেষ বিকল্পটি পছন্দ করি। এইভাবে আমি অনুরোধ (উত্পন্ন করার সময়, ফাইলের আকার, ত্রুটি বার্তাগুলি ইত্যাদি) সম্পর্কে তথ্য ফিরে পেতে পারি এবং ডাউনলোড শুরু করার আগে আমি সেই তথ্যটিতে কাজ করতে পারি। ডাউনসাইড হ'ল সার্ভারে অতিরিক্ত ফাইল ম্যানেজমেন্ট।

এটি সম্পাদন করার অন্য কোনও উপায়? এই পদ্ধতিগুলির সম্পর্কে কোনও উপকার / ধারণা সম্পর্কে আমার সচেতন হওয়া উচিত?



6
এটি আগে "কিছুটা" ছিল, সুতরাং এটি কীভাবে নকল
GiM

1
url = 'http://localhost/file.php?file='+ $('input').val(); window.open(url); একই ফলাফল পাওয়ার সহজ উপায়। পিএইচপি ফাইলে শিরোনামটি রাখুন। কোনও
এজাক্স

উত্তর:


171

লেট্রনজে এর সমাধানটি কেবল খুব সাধারণ পৃষ্ঠাগুলির জন্য কাজ করে। document.body.innerHTML +=শরীরের HTML পাঠ্য গ্রহণ করে, iframe এইচটিএমএল সংযোজন করে এবং পৃষ্ঠাটির অভ্যন্তরীণ এইচটিএমএলকে সেই স্ট্রিংয়ে সেট করে। এটি অন্যান্য বিষয়গুলির মধ্যে আপনার পৃষ্ঠাতে থাকা কোনও ইভেন্টের বাইন্ডিংগুলি মুছে ফেলবে। appendChildপরিবর্তে একটি উপাদান তৈরি করুন এবং ব্যবহার করুন।

$.post('/create_binary_file.php', postData, function(retData) {
  var iframe = document.createElement("iframe");
  iframe.setAttribute("src", retData.url);
  iframe.setAttribute("style", "display: none");
  document.body.appendChild(iframe);
}); 

বা jQuery ব্যবহার করে

$.post('/create_binary_file.php', postData, function(retData) {
  $("body").append("<iframe src='" + retData.url+ "' style='display: none;' ></iframe>");
}); 

এটি আসলে কী করে: ভেরিয়েবল পোস্টডেটাতে ডেটা সহ /create_binary_file.php এ একটি পোস্ট সম্পাদন করুন; যদি সেই পোস্টটি সফলভাবে সম্পন্ন হয় তবে পৃষ্ঠার শরীরে একটি নতুন iframe যুক্ত করুন। অনুমানটি হ'ল /create_binary_file.php এর প্রতিক্রিয়াতে একটি মান 'url' অন্তর্ভুক্ত থাকবে, যা ইউআরএল যে উত্পন্ন পিডিএফ / এক্সএলএস / ইত্যাদি ফাইল ডাউনলোড করা যায় be সেই পৃষ্ঠায় একটি আইফ্রেমে যুক্ত করা যা সেই URL এর উল্লেখ করে যা ওয়েব সার্ভারের উপযুক্ত মাইম টাইপ কনফিগারেশন রয়েছে তা ধরে নিয়ে ব্রাউজারটি ফাইলটি ডাউনলোড করতে উত্সাহিত করবে।


1
আমি সম্মত, এটি ব্যবহার করার চেয়ে ভাল +=এবং আমি সেই অনুযায়ী আমার অ্যাপ্লিকেশন আপডেট করব। ধন্যবাদ!
টুরেন

3
আমি এই ধারণা পছন্দ করি, কিন্তু ক্রোম কনসোল এই বার্তাটি রয়েছে: Resource interpreted as Document but transferred with MIME type application/pdf। তারপরে এটি আমাকে সতর্ক করে দেয় ফাইলটি বিপজ্জনক হতে পারে। আমি যদি retData.url সরাসরি পরিদর্শন করি তবে কোনও সতর্কতা বা সমস্যা নেই।
মাইকেল আইরি

ইন্টারনেটের আশেপাশে দেখে মনে হচ্ছে আপনার আইফ্রেমে পিডিএফ নিয়ে সমস্যা থাকতে পারে যদি আপনার সার্ভারটি সঠিকভাবে কন্টেন্ট-টাইপ এবং কনটেন্ট-ডিসপজিশন সেট না করে থাকে। আমি নিজেই এই সমাধানটি নিজেই ব্যবহার করি নি, কেবল একটি পূর্ববর্তী সমাধানটি পরিষ্কার করে দিয়েছি, তাই অন্য কোনও উপদেশ আমার ভয় নেই।
স্যামস্টেফেন্স

1
@ টাওরেন: আপনি যদি সম্মত হন যে এটি একটি উত্তম উত্তর, তবে নোট করুন যে আপনি যে কোনও সময় গৃহীত উত্তরটি স্যুইচ করতে পারেন - বা এমনকি গ্রহণযোগ্য চিহ্নটি পুরোপুরি সরিয়ে ফেলতে পারেন। কেবলমাত্র নতুন উত্তরটি পরীক্ষা করে দেখুন এবং গ্রহণযোগ্য চিহ্ন স্থানান্তরিত হবে। (ওল্ড প্রশ্ন, কিন্তু এটা সম্প্রতি পতাকা আপ আনা হয়েছিল।)
BoltClock

5
ভাবা retData.url কি হতে পারে?
মার্ক থিয়েন

48

আমি ব্লবস ব্যবহার করে এমন একটি অপশন নিয়ে প্রায় খেলছি। আমি এটি পাঠ্য দলিলগুলি ডাউনলোড করতে সক্ষম হয়েছি এবং আমি পিডিএফ ডাউনলোড করেছি (তবে সেগুলি দুর্নীতিগ্রস্থ হয়েছে)।

ব্লব এপিআই ব্যবহার করে আপনি নিম্নলিখিতগুলি করতে সক্ষম হবেন:

$.post(/*...*/,function (result)
{
    var blob=new Blob([result]);
    var link=document.createElement('a');
    link.href=window.URL.createObjectURL(blob);
    link.download="myFileName.txt";
    link.click();

});

এটি IE 10+, ক্রোম 8+, এফএফ 4+। Https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL দেখুন

এটি কেবল ক্রোম, ফায়ারফক্স এবং অপেরাতে ফাইলটি ডাউনলোড করবে। এটি ব্রাউজারটিকে ডাউনলোড করতে বাধ্য করার জন্য অ্যাঙ্কর ট্যাগ এ ডাউনলোড অ্যাট্রিবিউট ব্যবহার করে।


1
আইই এবং সাফারিতে ডাউনলোড বৈশিষ্ট্যের জন্য কোনও সমর্থন নেই :( ( caniuse.com/#feat=download ) a আপনি একটি নতুন উইন্ডো খুলতে পারেন এবং সেখানে সামগ্রী রাখতে পারেন, তবে কোনও পিডিএফ বা এক্সেল সম্পর্কে নিশ্চিত নন ...
মারিয়াল জুয়ান

1
ফোন করার পরে আপনার ব্রাউজারের মেমরিটি মুক্ত করা উচিত click:window.URL.revokeObjectURL(link.href);
এডওয়ার্ড ব্রেই

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

2
এটি বাইনারি ফাইলগুলিকে দূষিত করবে, কারণ তারা এনকোডিং ব্যবহার করে
স্ট্রিতে

2
পিডিএফগুলির সাথে এখানে ব্যবহার করা তথ্যের হিসাবে দুর্নীতিগ্রস্থ না হওয়ার জন্য মাইমটাইপগুলি
মাতেও টিবাউকিরা

18

আমি এই ধরণের পুরাতন জানি, তবে আমি মনে করি আমি আরও মার্জিত সমাধান নিয়ে এসেছি। আমার ঠিক একই সমস্যা ছিল. আমি যে সমস্যার সমাধানের পরামর্শ দিয়েছিলাম সেগুলি হ'ল তারা সকলেই ফাইলটি সার্ভারে সংরক্ষণ করা প্রয়োজন, তবে আমি সার্ভারে থাকা ফাইলগুলি সংরক্ষণ করতে চাইনি, কারণ এটি অন্যান্য সমস্যাগুলির সূচনা করেছিল (সুরক্ষা: ফাইলটি তখন অ্যাক্সেস করতে পারে) অ-অনুমোদনপ্রাপ্ত ব্যবহারকারী, ক্লিনআপ: আপনি কখন এবং ফাইলগুলি থেকে মুক্তি পাবেন)। এবং আপনার মতো, আমার ডেটা জটিল, নেস্টেড জেএসওএন অবজেক্ট ছিল যা ফর্মের মধ্যে রাখা কঠিন।

আমি যা করেছি তা হ'ল দুটি সার্ভার ফাংশন তৈরি করা। প্রথমটি যাচাই করে ডেটা। যদি কোনও ত্রুটি ঘটে থাকে তবে তা ফিরিয়ে দেওয়া হবে। এটি কোনও ত্রুটি না হলে আমি বেস 64 স্ট্রিং হিসাবে সিরিয়ালযুক্ত / এনকোডযুক্ত সমস্ত পরামিতিগুলি ফিরিয়ে দিয়েছি। তারপরে, ক্লায়েন্টে আমার একটি ফর্ম রয়েছে যাতে কেবল একটি লুকানো ইনপুট রয়েছে এবং দ্বিতীয় সার্ভার ফাংশনে পোস্ট রয়েছে posts আমি গোপন ইনপুটটি বেস 64 স্ট্রিংয়ে সেট করে ফর্ম্যাটটি জমা দেব। দ্বিতীয় সার্ভারের ফাংশন প্যারামিটারগুলি ডিকোড / ডিসায়ারাইজ করে এবং ফাইলটি উত্পন্ন করে। ফর্মটি একটি নতুন উইন্ডো বা পৃষ্ঠায় একটি আইফ্রেমে জমা দিতে পারে এবং ফাইলটি খুলবে।

আরও কিছু কাজ জড়িত রয়েছে, এবং সম্ভবত কিছুটা বেশি প্রক্রিয়াজাতকরণ রয়েছে, তবে সামগ্রিকভাবে, আমি এই সমাধানটি দিয়ে আরও অনেক ভাল অনুভব করেছি।

কোড সি # / এমভিসিতে রয়েছে

    public JsonResult Validate(int reportId, string format, ReportParamModel[] parameters)
    {
        // TODO: do validation

        if (valid)
        {
            GenerateParams generateParams = new GenerateParams(reportId, format, parameters);

            string data = new EntityBase64Converter<GenerateParams>().ToBase64(generateParams);

            return Json(new { State = "Success", Data = data });
        }

        return Json(new { State = "Error", Data = "Error message" });
    }

    public ActionResult Generate(string data)
    {
        GenerateParams generateParams = new EntityBase64Converter<GenerateParams>().ToEntity(data);

        // TODO: Generate file

        return File(bytes, mimeType);
    }

ক্লায়েন্ট উপর

    function generate(reportId, format, parameters)
    {
        var data = {
            reportId: reportId,
            format: format,
            params: params
        };

        $.ajax(
        {
            url: "/Validate",
            type: 'POST',
            data: JSON.stringify(data),
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            success: generateComplete
        });
    }

    function generateComplete(result)
    {
        if (result.State == "Success")
        {
            // this could/should already be set in the HTML
            formGenerate.action = "/Generate";
            formGenerate.target = iframeFile;

            hidData = result.Data;
            formGenerate.submit();
        }
        else
            // TODO: display error messages
    }

1
আমি এই সমাধানটি ভালভাবে দেখিনি, তবে এটি লক্ষ্য করার মতো যে, create_binary_file.php ব্যবহার করে সমাধানের জন্য ফাইলগুলির ডিস্কে সংরক্ষণ করার দরকার নেই। Create_binary_file.php মেমরিতে বাইনারি ফাইল উত্পন্ন করা সম্পূর্ণভাবে সম্ভব হবে।
স্যামস্টেফেনস

11

একটি সহজ উপায় আছে, একটি ফর্ম তৈরি করুন এবং এটি পোস্ট করুন, যদি পৃষ্ঠার পুনরায় সেট করার ঝুঁকি থাকে তবে রিটার্ন মাইম টাইপ এমন কোনও কিছু যা ব্রাউজার খোলে, তবে সিএসভি এবং এর জন্য এটি নিখুঁত

উদাহরণের জন্য আন্ডারস্কোর এবং jquery প্রয়োজন

var postData = {
    filename:filename,
    filecontent:filecontent
};
var fakeFormHtmlFragment = "<form style='display: none;' method='POST' action='"+SAVEAS_PHP_MODE_URL+"'>";
_.each(postData, function(postValue, postKey){
    var escapedKey = postKey.replace("\\", "\\\\").replace("'", "\'");
    var escapedValue = postValue.replace("\\", "\\\\").replace("'", "\'");
    fakeFormHtmlFragment += "<input type='hidden' name='"+escapedKey+"' value='"+escapedValue+"'>";
});
fakeFormHtmlFragment += "</form>";
$fakeFormDom = $(fakeFormHtmlFragment);
$("body").append($fakeFormDom);
$fakeFormDom.submit();

এইচটিএমএল, পাঠ্য এবং এই জাতীয় জিনিসের জন্য, নিশ্চিত করুন যে মাইমটাইপটি অ্যাপ্লিকেশন / অক্টেট-স্ট্রিমের মতো কিছু জিনিস

পিএইচপি কোড

<?php
/**
 * get HTTP POST variable which is a string ?foo=bar
 * @param string $param
 * @param bool $required
 * @return string
 */
function getHTTPPostString ($param, $required = false) {
    if(!isset($_POST[$param])) {
        if($required) {
            echo "required POST param '$param' missing";
            exit 1;
        } else {
            return "";
        }
    }
    return trim($_POST[$param]);
}

$filename = getHTTPPostString("filename", true);
$filecontent = getHTTPPostString("filecontent", true);

header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$filename\"");
echo $filecontent;

8

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

  1. এ লুক তথ্য URI স্কিম । বাইনারি ডেটা যদি ছোট হয় তবে আপনি সম্ভবত ইউআরআইতে উইন্ডো পাসিং ডেটা খুলতে জাভাস্ক্রিপ্ট ব্যবহার করতে পারেন।
  2. স্থানীয় ফাইল সিস্টেমে ডেটা সংরক্ষণ করতে এবং সেখান থেকে এটিকে খুলতে উইন্ডোজ / আইই এর একমাত্র সমাধান .NET নিয়ন্ত্রণ বা ফাইলসিস্টেমঅজেক্ট থাকতে হবে।

ধন্যবাদ, আমি ডেটা ইউআরআই স্কিম সম্পর্কে সচেতন ছিলাম না। দেখে মনে হচ্ছে একক অনুরোধে এটি করার একমাত্র উপায়। তবে এটি যে দিক দিয়ে যেতে চাইছে তা আসলে নয়।
টুরেন

ক্লায়েন্টের প্রয়োজনীয়তার কারণে আমি প্রতিক্রিয়াতে সার্ভারের শিরোনামগুলি ব্যবহার করে এই সমস্যার সমাধান করেছি ( Content-Disposition: attachment;filename="file.txt"), তবে আমি সত্যিই পরবর্তী সময় এই পদ্ধতির চেষ্টা করতে চাই। আমি এর URIআগে থাম্বনেইলের জন্য ডেটা ব্যবহার করেছি, তবে এটি ডাউনলোডের জন্য ব্যবহার করার মতো ঘটনা আমার কাছে কখনও ঘটেনি - এই নটটি ভাগ করে নেওয়ার জন্য ধন্যবাদ।
brichins

8

এই প্রশ্নটি জিজ্ঞাসা করার পরে অনেক দিন হয়েছে তবে আমার একই চ্যালেঞ্জ ছিল এবং আমার সমাধানটি ভাগ করে নিতে চাই। এটি অন্যান্য উত্তরগুলির উপাদান ব্যবহার করে তবে আমি এটির সম্পূর্ণরূপে এটি খুঁজে পাইনি। এটি কোনও ফর্ম বা একটি আইফ্রেমে ব্যবহার করে না তবে এটির জন্য একটি পোস্ট / অনুরোধ জুটির প্রয়োজন নেই। অনুরোধগুলির মধ্যে ফাইলটি সংরক্ষণ করার পরিবর্তে এটি পোস্টের ডেটা সংরক্ষণ করে। এটি সহজ এবং কার্যকর উভয়ই বলে মনে হচ্ছে।

মক্কেল

var apples = new Array(); 
// construct data - replace with your own
$.ajax({
   type: "POST",
   url: '/Home/Download',
   data: JSON.stringify(apples),
   contentType: "application/json",
   dataType: "text",

   success: function (data) {
      var url = '/Home/Download?id=' + data;
      window.location = url;
   });
});

সার্ভার

[HttpPost]
// called first
public ActionResult Download(Apple[] apples)
{
   string json = new JavaScriptSerializer().Serialize(apples);
   string id = Guid.NewGuid().ToString();
   string path = Server.MapPath(string.Format("~/temp/{0}.json", id));
   System.IO.File.WriteAllText(path, json);

   return Content(id);
}

// called next
public ActionResult Download(string id)
{
   string path = Server.MapPath(string.Format("~/temp/{0}.json", id));
   string json = System.IO.File.ReadAllText(path);
   System.IO.File.Delete(path);
   Apple[] apples = new JavaScriptSerializer().Deserialize<Apple[]>(json);

   // work with apples to build your file in memory
   byte[] file = createPdf(apples); 

   Response.AddHeader("Content-Disposition", "attachment; filename=juicy.pdf");
   return File(file, "application/pdf");
}

1
আমি মনে করি আমার এই সমাধানটি সবচেয়ে ভাল লেগেছে। আমার ক্ষেত্রে যদিও আমি ফাইলটি উত্পন্ন করছি, তাই আমি মনে করি যে ফাইলটি অ্যাক্সেস না হওয়া অবধি মেমরিতে রাখার চেষ্টা করব এবং এটি ডাউনলোড হওয়ার পরে মেমরিটি মুক্ত করে ফেলব তাই আমাকে কখনই ডিস্কে লিখতে হবে না।
বিভারনন

5
$scope.downloadSearchAsCSV = function(httpOptions) {
  var httpOptions = _.extend({
    method: 'POST',
    url:    '',
    data:   null
  }, httpOptions);
  $http(httpOptions).then(function(response) {
    if( response.status >= 400 ) {
      alert(response.status + " - Server Error \nUnable to download CSV from POST\n" + JSON.stringify(httpOptions.data));
    } else {
      $scope.downloadResponseAsCSVFile(response)
    }
  })
};
/**
 * @source: https://github.com/asafdav/ng-csv/blob/master/src/ng-csv/directives/ng-csv.js
 * @param response
 */
$scope.downloadResponseAsCSVFile = function(response) {
  var charset = "utf-8";
  var filename = "search_results.csv";
  var blob = new Blob([response.data], {
    type: "text/csv;charset="+ charset + ";"
  });

  if (window.navigator.msSaveOrOpenBlob) {
    navigator.msSaveBlob(blob, filename); // @untested
  } else {
    var downloadContainer = angular.element('<div data-tap-disabled="true"><a></a></div>');
    var downloadLink      = angular.element(downloadContainer.children()[0]);
    downloadLink.attr('href', window.URL.createObjectURL(blob));
    downloadLink.attr('download', "search_results.csv");
    downloadLink.attr('target', '_blank');

    $document.find('body').append(downloadContainer);

    $timeout(function() {
      downloadLink[0].click();
      downloadLink.remove();
    }, null);
  }

  //// Gets blocked by Chrome popup-blocker
  //var csv_window = window.open("","","");
  //csv_window.document.write('<meta name="content-type" content="text/csv">');
  //csv_window.document.write('<meta name="content-disposition" content="attachment;  filename=data.csv">  ');
  //csv_window.document.write(response.data);
};

3

সম্পূর্ণরূপে মূল পোস্টের উত্তর নয়, তবে সার্ভারে একটি জেসন-অবজেক্ট পোস্ট করার জন্য এবং গতিশীলভাবে একটি ডাউনলোড জেনারেশনের জন্য একটি দ্রুত এবং নোংরা সমাধান।

ক্লায়েন্ট পক্ষ jQuery:

var download = function(resource, payload) {
     $("#downloadFormPoster").remove();
     $("<div id='downloadFormPoster' style='display: none;'><iframe name='downloadFormPosterIframe'></iframe></div>").appendTo('body');
     $("<form action='" + resource + "' target='downloadFormPosterIframe' method='post'>" +
      "<input type='hidden' name='jsonstring' value='" + JSON.stringify(payload) + "'/>" +
      "</form>")
      .appendTo("#downloadFormPoster")
      .submit();
}

.. এবং তারপরে সার্ভারসাইডে জসন-স্ট্রিংটি ডিকোডিং এবং ডাউনলোডের জন্য শিরোনাম স্থাপন (পিএইচপি উদাহরণ):

$request = json_decode($_POST['jsonstring']), true);
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=export.csv');
header('Pragma: no-cache');

আমি এই সমাধানটি পছন্দ করি। ওপি-র প্রশ্নের মধ্যে মনে হচ্ছে অনুরোধকারী কোনও ফাইল ডাউনলোড বা জেএসওএন ডেটা আশা করবেন কিনা তা জানে, তাই সে ক্লায়েন্টের শেষে সিদ্ধান্ত নিতে পারে এবং সার্ভারের শেষের সিদ্ধান্ত না নিয়ে ভিন্ন URL এ পোস্ট করতে পারে।
স্যাম

2

আমি মনে করি সবচেয়ে ভাল পদ্ধতির সমন্বয় ব্যবহার করা, আপনার দ্বিতীয় পদ্ধতির মনে হয় ব্রাউজারগুলি এতে জড়িত যেখানে মার্জিত সমাধান।

কিভাবে কল করা হয় তার উপর নির্ভর করে। (এটি ব্রাউজার বা ওয়েব পরিষেবা কল যাই হোক না কেন) আপনি ব্রাউজারে ইউআরএল প্রেরণ এবং অন্য কোনও ওয়েব পরিষেবা ক্লায়েন্টকে কাঁচা ডেটা প্রেরণ সহ দুটির সংমিশ্রণ ব্যবহার করতে পারেন।


আমার দ্বিতীয় পদ্ধতিটি এখন আমার কাছে আরও আবেদনময়ী দেখাচ্ছে। এটি নিশ্চিত করার জন্য ধন্যবাদ একটি উপযুক্ত সমাধান। আপনি কি পরামর্শ দিচ্ছেন যে আমি জসন বস্তুটিতে একটি অতিরিক্ত মান পাস করেছি যা ইঙ্গিত করে যে এই অনুরোধটি কোনও ব্রাউজার থেকে একটি ওয়েব সার্ভিস কলের পরিবর্তে এজ্যাক্স কল হিসাবে করা হচ্ছে? এটি সম্পাদন করার বিভিন্ন উপায় আছে যা আমি ভাবতে পারি, তবে আপনি কোন কৌশলটি ব্যবহার করবেন?
টুরেন

এটি ব্যবহারকারী-এজেন্ট HTTP শিরোনাম দ্বারা নির্ধারণ করা যায় না? বা অন্য কোনও HTTP শিরোনাম?
নাইকাস

1

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

মক্কেলের পক্ষে

function exportStaffCSV(t) {
   
    var postData = { checkOne: t };
    $.ajax({
        type: "POST",
        url: "/Admin/Staff/exportStaffAsCSV",
        data: postData,
        success: function (data) {
            SuccessMessage("file download will start in few second..");
            var url = '/Admin/Staff/DownloadCSV?data=' + data;
            window.location = url;
        },
       
        traditional: true,
        error: function (xhr, status, p3, p4) {
            var err = "Error " + " " + status + " " + p3 + " " + p4;
            if (xhr.responseText && xhr.responseText[0] == "{")
                err = JSON.parse(xhr.responseText).Message;
            ErrorMessage(err);
        }
    });

}

সার্ভার সাইড

 [HttpPost]
    public string exportStaffAsCSV(IEnumerable<string> checkOne)
    {
        StringWriter sw = new StringWriter();
        try
        {
            var data = _db.staffInfoes.Where(t => checkOne.Contains(t.staffID)).ToList();
            sw.WriteLine("\"First Name\",\"Last Name\",\"Other Name\",\"Phone Number\",\"Email Address\",\"Contact Address\",\"Date of Joining\"");
            foreach (var item in data)
            {
                sw.WriteLine(string.Format("\"{0}\",\"{1}\",\"{2}\",\"{3}\",\"{4}\",\"{5}\",\"{6}\"",
                    item.firstName,
                    item.lastName,
                    item.otherName,
                    item.phone,
                    item.email,
                    item.contact_Address,
                    item.doj
                    ));
            }
        }
        catch (Exception e)
        {

        }
        return sw.ToString();

    }

    //On ajax success request, it will be redirected to this method as a Get verb request with the returned date(string)
    public FileContentResult DownloadCSV(string data)
    {
        return File(new System.Text.UTF8Encoding().GetBytes(data), System.Net.Mime.MediaTypeNames.Application.Octet, filename);
        //this method will now return the file for download or open.
    }

শুভকামনা।


2
এটি ছোট ফাইলগুলির জন্য কাজ করবে। তবে আপনার কাছে যদি একটি বড় ফাইল থাকে তবে আপনি ইউআরএলটি দীর্ঘায়িত হওয়ার সমস্যায় চলে যাবেন। এটি 1000 টি রেকর্ড সহ চেষ্টা করুন, এটি ভেঙ্গে যাবে এবং কেবলমাত্র ডেটার অংশ রফতানি করবে।
মাইকেল মেরেল

1

এটি অনেক আগে পাওয়া গেছে এবং এটি নিখুঁতভাবে কাজ করে!

let payload = {
  key: "val",
  key2: "val2"
};

let url = "path/to/api.php";
let form = $('<form>', {'method': 'POST', 'action': url}).hide();
$.each(payload, (k, v) => form.append($('<input>', {'type': 'hidden', 'name': k, 'value': v})) );
$('body').append(form);
form.submit();
form.remove();

0

সার্ভারে ফাইলটি সংরক্ষণ এবং এটি পুনরুদ্ধার করার পরিবর্তে আরেকটি পদ্ধতি হ'ল .NET 4.0+ অবজেক্টকে দ্বিতীয় অ্যাকশন (যে সময়ে এটি নির্দিষ্টভাবে ফেলে দেওয়া যেতে পারে) অবধি সংক্ষিপ্ত মেয়াদ সহ ব্যবহার করা হবে। কলটি করার জন্য আমি জিকিউরি অ্যাজাক্সটি যে কারণে ব্যবহার করতে চাই তা হ'ল এটি অ্যাসিনক্রোনাস। আমার গতিশীল পিডিএফ ফাইল তৈরি করতে বেশ খানিকটা সময় সময় লাগে এবং আমি সেই সময়ে একটি ব্যস্ত স্পিনার ডায়ালগ প্রদর্শন করি (এটি অন্যান্য কাজও করার অনুমতি দেয়)। ব্লব তৈরির জন্য "সাফল্য:" এ ফিরে আসা ডেটা ব্যবহারের পদ্ধতির নির্ভরযোগ্যভাবে কাজ করে না। এটি পিডিএফ ফাইলের বিষয়বস্তুর উপর নির্ভর করে। প্রতিক্রিয়াতে এটি সহজে ডেটা দ্বারা দূষিত হয়, যদি এটি সম্পূর্ণ পাঠ্য না হয় যা অ্যাজাক্স হ্যান্ডেল করতে পারে এমন সমস্ত বিষয়।


0

সমাধান

সামগ্রী-বিশৃঙ্খলা সংযুক্তি আমার পক্ষে কাজ করে বলে মনে হচ্ছে:

self.set_header("Content-Type", "application/json")
self.set_header("Content-Disposition", 'attachment; filename=learned_data.json')

কার্যসংক্রান্ত

আবেদন / অক্টেট-স্ট্রীম

আমার সাথে জেএসএনের সাথে আমার অনুরূপ কিছু ঘটেছিল, সার্ভার সাইডে আমার জন্য আমি সেলফ.সেটহেডারে ("বিষয়বস্তুর ধরণ", " অ্যাপ্লিকেশন / জেসন ") সেট করে রাখছিলাম তবে যখন আমি এটিকে পরিবর্তন করেছি:

self.set_header("Content-Type", "application/octet-stream")

এটি স্বয়ংক্রিয়ভাবে এটি ডাউনলোড হয়েছে।

এছাড়াও জেনে রাখুন যে ফাইলটি এখনও .json প্রত্যয় ধরে রাখার জন্য আপনাকে ফাইলের নাম শিরোনামে এটি করতে হবে:

self.set_header("Content-Disposition", 'filename=learned_data.json')

-1

এইচটিএমএল 5 দিয়ে আপনি কেবল একটি অ্যাঙ্কর তৈরি করতে এবং এটিতে ক্লিক করতে পারেন। এটি শিশু হিসাবে নথিতে যুক্ত করার দরকার নেই।

const a = document.createElement('a');
a.download = '';
a.href = urlForPdfFile;
a.click();

সব শেষ.

আপনি যদি ডাউনলোডের জন্য একটি বিশেষ নাম রাখতে চান তবে এটি downloadএট্রিবিউটটি দিয়ে দিন:

const a = document.createElement('a');
a.download = 'my-special-name.pdf';
a.href = urlForPdfFile;
a.click();

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