मैं Angular2 या अधिक से अधिक फ़ाइल कैसे डाउनलोड करूं


182

मेरे पास एक WebApi / MVC ऐप है जिसके लिए मैं एक कोणीय 2 क्लाइंट (MVC को बदलने के लिए) विकसित कर रहा हूं। मुझे यह समझने में कुछ परेशानी हो रही है कि कोणीय फ़ाइल को कैसे बचाता है।

अनुरोध ठीक है (एमवीसी के साथ ठीक काम करता है, और हम प्राप्त डेटा को लॉग इन कर सकते हैं) लेकिन मैं यह नहीं जान सकता कि डाउनलोड किए गए डेटा को कैसे बचाया जाए (मैं इस पोस्ट में ज्यादातर उसी तर्क का पालन कर रहा हूं )। मुझे यकीन है कि यह मूर्खतापूर्ण सरल है, लेकिन अभी तक मैं बस इसे समझ नहीं रहा हूं।

घटक फ़ंक्शन का कोड नीचे है। मैंने अलग-अलग विकल्पों की कोशिश की है, जहाँ तक मुझे समझा गया था, वहाँ तक जाने के लिए बूँद रास्ता होना चाहिए, लेकिन इसमें कोई फ़ंक्शन नहीं createObjectURLहै URL। मुझे URLविंडो की परिभाषा भी नहीं मिल रही है, लेकिन जाहिर है कि यह मौजूद है। यदि मैं FileSaver.jsमॉड्यूल का उपयोग करता हूं तो मुझे वही त्रुटि मिलती है। इसलिए मुझे लगता है कि यह कुछ ऐसा है जो हाल ही में बदल गया है या अभी तक लागू नहीं हुआ है। मैं A2 में फ़ाइल सेव को कैसे ट्रिगर कर सकता हूं?

downloadfile(type: string){

    let thefile = {};
    this.pservice.downloadfile(this.rundata.name, type)
        .subscribe(data => thefile = new Blob([data], { type: "application/octet-stream" }), //console.log(data),
                    error => console.log("Error downloading the file."),
                    () => console.log('Completed file download.'));

    let url = window.URL.createObjectURL(thefile);
    window.open(url);
}

संपूर्णता की खातिर, डेटा को लाने वाली सेवा नीचे है, लेकिन केवल एक चीज जो अनुरोध को जारी करती है और यदि वह सफल होती है, तो मैपिंग के बिना डेटा को पारित करना है:

downloadfile(runname: string, type: string){
   return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type)
            .catch(this.logAndPassOn);
}

आप इस विधि से बड़ी फ़ाइलों को डाउनलोड नहीं कर सकते। आप प्रति टैब में मेमोरी लिमिट को हिट करेंगे। यह 1-2GB जितना कम हो सकता है।
मैथ्यू बी।

@MatthewB। काश आपने कहा होता तो बेहतर था।
स्टीव

बड़े फ़ाइल डाउनलोड के लिए आपको एक नया टैब निर्दिष्ट करने की आवश्यकता होती है जैसे कि <A> क्लिक करते समय, लक्ष्य को "_blank" के बराबर करने की आवश्यकता होती है या फ़ॉर्म सबमिट करना होता है। मुझे नहीं लगता कि अजाक्स-शैली के अनुरोधों के साथ बड़े फ़ाइल आकार सीमा के आसपास पाने का एक साफ तरीका है।
मत्ती B.

जवाबों:


181

समस्या यह है कि अवलोकनीय एक और संदर्भ में चलता है, इसलिए जब आप URL संस्करण बनाने का प्रयास करते हैं, तो आपके पास एक खाली वस्तु होती है, न कि आप जो बूँद चाहते हैं।

इसे हल करने के लिए मौजूद कई तरीकों में से एक निम्नानुसार है:

this._reportService.getReport().subscribe(data => this.downloadFile(data)),//console.log(data),
                 error => console.log('Error downloading the file.'),
                 () => console.info('OK');

जब अनुरोध तैयार हो जाता है, तो यह फ़ंक्शन को "डाउनलोड फ़ील" कहेगा जिसे इस प्रकार परिभाषित किया गया है:

downloadFile(data: Response) {
  const blob = new Blob([data], { type: 'text/csv' });
  const url= window.URL.createObjectURL(blob);
  window.open(url);
}

बूँद पूरी तरह से बनाई गई है और इसलिए URL संस्करण, यदि नई विंडो नहीं खुलती है, तो कृपया जाँच लें कि आपने 'rxjs / Rx' पहले ही आयात कर लिया है;

  import 'rxjs/Rx' ;

मैं आशा करता हूं यह आपकी मदद कर सकते हैं।


9
क्या है this._reportService.getReport()और यह क्या लौटाता है?
बुर्जुआ

3
@Burjua getReport()रिटर्न एकthis.http.get(PriceConf.download.url)
जी-रूह

6
मुद्दा मैं यह है कि खिड़की खुलता है और तुरंत फ़ाइल डाउनलोड नहीं करता बंद कर देता है
ब्रैडेन ब्राउन

7
हम यहाँ फ़ाइल नाम कैसे सेट कर सकते हैं? डिफ़ॉल्ट रूप से यह नाम के रूप में एक संख्यात्मक मूल्य चुनता है
सौरभ

8
मैंने एपीआई प्रतिक्रिया से फ़ाइल डाउनलोड करने के लिए उपरोक्त कोड का उपयोग किया है, लेकिन मुझे बूँद भाग बनाने में कुछ त्रुटि हो रही है "टाइप प्रतिक्रिया बूँद टाइप करने के लिए असाइन नहीं की जाती है"। अगर किसी को यह समस्या पता है तो कृपया मदद करें
knbibin

92

यह कोशिश करो !

1 - शो सेव / ओपन फाइल पॉप-अप के लिए निर्भरता स्थापित करें

npm install file-saver --save
npm install @types/file-saver --save

2- डेटा रिकवर करने के लिए इस फ़ंक्शन के साथ एक सेवा बनाएं

downloadFile(id): Observable<Blob> {
    let options = new RequestOptions({responseType: ResponseContentType.Blob });
    return this.http.get(this._baseUrl + '/' + id, options)
        .map(res => res.blob())
        .catch(this.handleError)
}

3- घटक में 'फ़ाइल-सेवर' के साथ बूँद को पार्स करें

import {saveAs as importedSaveAs} from "file-saver";

  this.myService.downloadFile(this.id).subscribe(blob => {
            importedSaveAs(blob, this.fileName);
        }
    )

यह मेरे लिए काम करता है!


1
मैंने @Alejandro के उत्तर के साथ संयोजन में चरण 2 का उपयोग किया और यह फ़ाइल-सेवर को स्थापित करने की आवश्यकता के बिना काम किया ...
Ewert

5
धन्यवाद! यह पूरी तरह से काम करता है! मुझे आश्चर्य है कि अगर हम प्रतिक्रिया के हेडर पर परिभाषित फ़ाइल नाम प्राप्त कर सकते हैं। क्या यह संभव है?
jfajunior

2
त्रुटि Av5 प्रकार का अनुरोध '' प्रकार '' के हेडर के पैरामीटर के लिए अनुरोध योग्य नहीं है? {[शीर्ष लेख: स्ट्रिंग]: स्ट्रिंग | स्ट्रिंग []; };
giveJob

यह एक बड़ी फाइल डाउनलोड के लिए उपयुक्त नहीं है।
Reven

61

यदि आपको अनुरोध में हेडर जोड़ने की आवश्यकता नहीं है , तो Angular2 में एक फ़ाइल डाउनलोड करने के लिए आप एक सरल कार्य कर सकते हैं :

window.location.href='http://example.com/myuri/report?param=x';

आपके घटक में।


4
क्या कोई यह बता सकता है कि यह उत्तर क्यों अस्वीकृत है? विषय कोणीय 2 का उपयोग करके फ़ाइल डाउनलोड करना है। यदि यह विधि एक सरल डाउनलोड करने के लिए काम करती है तो इसे एक वैध उत्तर के रूप में भी चिह्नित किया जाना चाहिए।
सौरभ शेट्टी

5
@ सौरभशेट्टी, यदि आप कस्टम हेडर भेजना चाहते हैं तो यह मदद नहीं करेगा, यदि आप उदाहरण के लिए ऑउटलेट टोकन भेजना चाहते हैं तो क्या होगा? यदि आप ओपी प्रश्न को देखते हैं तो आप देख सकते हैं कि वह उपयोग करता है authHttp!
ए। अकरम

6
मुझे समझ में नहीं आ रहा है, फिर भी इस जवाब से मेरी समस्या हल हो गई।
जोरीशोएबी

1
यदि आप सर्वर को किसी संदर्भ में url वापस करने देते हैं, तो सर्वर url तैयार कर सकता है। ex: ऑब्जेक्ट: MyRecord.Cover। कवर सर्वर में एक छवि के लिए एक यूआरएल हो सकता है। जब कॉलिंग माई (Myrecord) आती है तो आप सर्वर को तैयार किया गया url (कवर) वापस कर देते हैं, जिसमें सुरक्षा टोकन और अन्य हेडर सेट होते हैं।
जेन्स एलेनियस

2
यह एक जवाब है कि काम करता है। बस क्योंकि यह उपयोगी सुविधा यहाँ डालें> नहीं है कि यह एक जवाब नहीं बनाते हैं।
गबटन

47

यह उन लोगों के लिए है जो HttpClient और फ़ाइल-सेवर का उपयोग करके इसे करना चाहते हैं:

  1. फ़ाइल सेवर स्थापित करें

npm फ़ाइल सेवर-सेव स्थापित करें

npm @ प्रकार / फ़ाइल-सेवर - save स्थापित करें

एपीआई सेवा वर्ग:

export() {
    return this.http.get(this.download_endpoint, 
        {responseType: 'blob'});
}

घटक:

import { saveAs } from 'file-saver';
exportPdf() {
    this.api_service.export().subscribe(data => saveAs(data, `pdf report.pdf`));
}

1
डाउनलोड शुरू होने पर ब्राउज़र में फ़ाइलों को कैसे दिखाना है? मैं http हेडर में कंटेंट-लेंथ के रूप में फाइल भेज रहा हूं।
विनम्र डिकोडर

35

इस बारे में कैसा है?

this.http.get(targetUrl,{responseType:ResponseContentType.Blob})
        .catch((err)=>{return [do yourself]})
        .subscribe((res:Response)=>{
          var a = document.createElement("a");
          a.href = URL.createObjectURL(res.blob());
          a.download = fileName;
          // start download
          a.click();
        })

मैं इसके साथ कर सकता था।
अतिरिक्त पैकेज की आवश्यकता नहीं है।


3
इतना सरल अभी तक यह एक है जो निर्दोष रूप से काम करता है। यह डोम को अव्यवस्थित नहीं करता है, कोई भी तत्व नहीं बनाता है। मैंने इस समाधान को कुछ एब्स के साथ जोड़ा और यह एक आकर्षण की तरह काम करता है।
Chax

20

जैसा कि अलेजांद्रो कोरिडोर द्वारा उल्लेख किया गया है, यह एक साधारण गुंजाइश त्रुटि है। subscribeअतुल्यकालिक रूप से चलाया जाता है औरopen इस संदर्भ में रखा जाना चाहिए, ताकि डेटा लोड करना समाप्त जब हम डाउनलोड ट्रिगर।

उस ने कहा, इसे करने के दो तरीके हैं। डॉक्स सलाह देते हैं कि सेवा डेटा प्राप्त करने और मैप करने का ध्यान रखती है:

//On the service:
downloadfile(runname: string, type: string){
  var headers = new Headers();
  headers.append('responseType', 'arraybuffer');
  return this.authHttp.get( this.files_api + this.title +"/"+ runname + "/?file="+ type)
            .map(res => new Blob([res],{ type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }))
            .catch(this.logAndPassOn);
}

फिर, घटक पर हम केवल मैप किए गए डेटा के साथ सदस्यता लेते हैं और सौदा करते हैं। दो संभावनाएं हैं। पहला , जैसा कि मूल पोस्ट में सुझाया गया है, लेकिन एलेजैंड्रो द्वारा नोट किए गए एक छोटे से सुधार की आवश्यकता है:

//On the component
downloadfile(type: string){
  this.pservice.downloadfile(this.rundata.name, type)
      .subscribe(data => window.open(window.URL.createObjectURL(data)),
                  error => console.log("Error downloading the file."),
                  () => console.log('Completed file download.'));
  }

दूसरा तरीका FileReader का उपयोग करना होगा। तर्क समान है, लेकिन हम स्पष्ट रूप से डेटा लोड करने, नेस्टिंग से बचने और एसिंक्रोनस समस्या को हल करने के लिए FileReader का इंतजार कर सकते हैं।

//On the component using FileReader
downloadfile(type: string){
    var reader = new FileReader();
    this.pservice.downloadfile(this.rundata.name, type)
        .subscribe(res => reader.readAsDataURL(res), 
                    error => console.log("Error downloading the file."),
                    () => console.log('Completed file download.'));

    reader.onloadend = function (e) {
        window.open(reader.result, 'Excel', 'width=20,height=10,toolbar=0,menubar=0,scrollbars=no');
  }
}

नोट: मैं एक एक्सेल फाइल डाउनलोड करने की कोशिश कर रहा हूं, और भले ही डाउनलोड शुरू हो गया हो (इसलिए यह सवाल का जवाब देता है), फाइल भ्रष्ट है। भ्रष्ट फ़ाइल से बचने के लिए इस पोस्ट का उत्तर देखें


7
मुझे लगता है कि फ़ाइल दूषित होने का कारण यह है कि आप resबूँद में लोड कर रहे हैं और आप वास्तव में चाहते हैं res._body। हालांकि _bodyएक निजी चर है और सुलभ नहीं है। आज तक .blob()और .arrayBuffer()http प्रतिक्रिया पर ऑब्जेक्ट को कोणीय 2 में लागू नहीं किया गया है text()और json()केवल दो विकल्प हैं, लेकिन दोनों ही आपके शरीर को गला देंगे। क्या आपने हल खोज लिया?
sschueller

1
hi @rll, मैंने उपरोक्त चरणों का पालन किया और मुझे पूर्ण के रूप में सदस्यता मिल रही है। फिर भी मैं फ़ाइल को डाउनलोड नहीं कर पाया। मैं कोई त्रुटि भी नहीं देख सका। कृपया मदद करें
AishApp

1
2 विकल्प मुझे फ़ाइल डाउनलोड करने देता है, लेकिन यह पहले बैकग्राउंड में डेटा लोड करता है। क्या होगा अगर मेरे पास एक बड़ी फ़ाइल है जिसे डाउनलोड करना होगा?
f123

1
मेरा समाधान सिर्फ <a href=""></a>एक फ़ाइल डाउनलोड करने के लिए उपयोग करना है।
user2061057

1
मुझे पता है कि यह एक पुराना उत्तर है, लेकिन यह खोज परिणामों पर उच्च है और स्वीकृत उत्तर है: लाइन `हेडर.एपेंड ('रिस्पांस टाइप', 'सरणीबफ़र');` गलत है। यह एक विकल्प है, हेडर नहीं है। कृपया इसे ठीक करे। Aaaand ... शीर्षलेख बनाए जाते हैं और उनका उपयोग नहीं किया जाता है। अनुपयोगी।
स्टेवो

17

डाउनलोड *। कोणीय 2.4.x के लिए .zip समाधान: आपको '@ कोणीय / http' से ResponseContentType आयात करना होगा और प्रतिक्रिया को प्रतिक्रिया में बदलना होगा ResponseContentType.ArrayBuffer (डिफ़ॉल्ट रूप से यह ResponseContentType.Json द्वारा)

getZip(path: string, params: URLSearchParams = new URLSearchParams()): Observable<any> {
 let headers = this.setHeaders({
      'Content-Type': 'application/zip',
      'Accept': 'application/zip'
    });

 return this.http.get(`${environment.apiUrl}${path}`, { 
   headers: headers, 
   search: params, 
   responseType: ResponseContentType.ArrayBuffer //magic
 })
          .catch(this.formatErrors)
          .map((res:Response) => res['_body']);
}

16

नए कोणीय संस्करणों के लिए:

npm install file-saver --save
npm install @types/file-saver --save


import {saveAs} from 'file-saver/FileSaver';

this.http.get('endpoint/', {responseType: "blob", headers: {'Accept': 'application/pdf'}})
  .subscribe(blob => {
    saveAs(blob, 'download.pdf');
  });

धन्यवाद, कोणीय 8 के साथ काम करता है। पता नहीं क्यों यह खोजने के लिए बहुत मुश्किल था।
एमडीवे

11

अजाक्स के माध्यम से फाइल डाउनलोड करना हमेशा एक दर्दनाक प्रक्रिया होती है और मेरे विचार में सर्वर और ब्राउज़र को सामग्री प्रकार की बातचीत का यह काम करने देना सबसे अच्छा है।

मुझे लगता है कि यह सबसे अच्छा है

<a href="api/sample/download"></a> 

इसे करने के लिए। इसके लिए किसी नई विंडो को खोलने और उस तरह के सामान की भी आवश्यकता नहीं होती है।

आपके नमूने में MVC नियंत्रक नीचे दिए गए के समान हो सकता है:

[HttpGet("[action]")]
public async Task<FileContentResult> DownloadFile()
{
    // ...
    return File(dataStream.ToArray(), "text/plain", "myblob.txt");
}

1
आप सही हैं, लेकिन फिर आप सिंगल-पेज एप्लिकेशन के भीतर सर्वर त्रुटियों का प्रबंधन कैसे कर सकते हैं? एक त्रुटि के मामले में, आमतौर पर, एक REST सेवा JSON को त्रुटि के साथ लौटाती है, इस प्रकार JSON को किसी अन्य ब्राउज़र विंडो में खोलने के लिए आवेदन किया जाता है, जो वह नहीं है जिसे उपयोगकर्ता देखना चाहता है
Luca

2
यदि आपके पास एक पहुंच टोकन है, तो आपको यह प्रदान करना होगा कि यह काम नहीं करता है
chris31389

यह सादा और सरल है। लेकिन अगर आप कुछ प्रमाणीकरण करना चाहते हैं, तो एक बार टोकन की तरह कुछ होने की संभावना है। इसलिए, इसे इस तरह से रखने के बजाय, आपके पास url इस प्रकार हो सकता है: example.com/myuri/report?tokenid=1234-1233 और डेटाबेस में टोकन आईडी सत्यापित करें। बेशक यह एक साधारण परिदृश्य नहीं है और सभी स्थितियों में काम करता है, लेकिन ऐसी स्थिति में एक समाधान हो सकता है जहां, रिपोर्ट के लिए एक स्ट्रीम के रूप में लौटने से पहले आपके पास डेटाबेस तक पहुंच हो ..
GingerBeer

सर्वर से डाउनलोड यूआरएल प्राप्त करें। इसलिए सर्वर onl सुरक्षा टोकन के साथ url तैयार कर सकता है।
जेन्स एलेनियस

8

मैं 4.3 httpClient ऑब्जेक्ट के साथ कोणीय 4 का उपयोग कर रहा हूं। मैंने जेएस के तकनीकी ब्लॉग में पाया गया एक उत्तर को संशोधित किया, जो एक लिंक ऑब्जेक्ट बनाता है, इसे डाउनलोड करने के लिए उपयोग करता है, फिर इसे नष्ट कर देता है।

ग्राहक:

doDownload(id: number, contentType: string) {
    return this.http
        .get(this.downloadUrl + id.toString(), { headers: new HttpHeaders().append('Content-Type', contentType), responseType: 'blob', observe: 'body' })
}

downloadFile(id: number, contentType: string, filename:string)  {

    return this.doDownload(id, contentType).subscribe(  
        res => { 
            var url = window.URL.createObjectURL(res);
            var a = document.createElement('a');
            document.body.appendChild(a);
            a.setAttribute('style', 'display: none');
            a.href = url;
            a.download = filename;
            a.click();
            window.URL.revokeObjectURL(url);
            a.remove(); // remove the element
        }, error => {
            console.log('download error:', JSON.stringify(error));
        }, () => {
            console.log('Completed file download.')
        }); 

} 

इस.downloadUrl का मान पहले से एपीआई को इंगित करने के लिए सेट किया गया है। मैं अनुलग्नकों को डाउनलोड करने के लिए इसका उपयोग कर रहा हूं, इसलिए मुझे आईडी, सामग्री टाइप और फ़ाइल नाम पता है: मैं फ़ाइल को वापस करने के लिए एक एमवीसी एपीआई का उपयोग कर रहा हूं:

 [ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
    public FileContentResult GetAttachment(Int32 attachmentID)
    { 
        Attachment AT = filerep.GetAttachment(attachmentID);            
        if (AT != null)
        {
            return new FileContentResult(AT.FileBytes, AT.ContentType);  
        }
        else
        { 
            return null;
        } 
    } 

अनुलग्नक वर्ग इस तरह दिखता है:

 public class Attachment
{  
    public Int32 AttachmentID { get; set; }
    public string FileName { get; set; }
    public byte[] FileBytes { get; set; }
    public string ContentType { get; set; } 
}

फाइलरेप रिपॉजिटरी फाइल को डेटाबेस से वापस करती है।

आशा है कि यह किसी की मदद करता है :)


7

Redux पैटर्न का उपयोग करने वालों के लिए

मैंने उनके जवाब में @Hueue Cuevas नाम से फ़ाइल-सेवर में जोड़ा। Angular2 v। 2.3.1 का उपयोग करते हुए, मुझे @ प्रकार / फ़ाइल-सेवर में जोड़ने की आवश्यकता नहीं थी।

निम्न उदाहरण पीडीएफ के रूप में एक पत्रिका डाउनलोड करने के लिए है।

पत्रिका की कार्रवाई

public static DOWNLOAD_JOURNALS = '[Journals] Download as PDF';
public downloadJournals(referenceId: string): Action {
 return {
   type: JournalActions.DOWNLOAD_JOURNALS,
   payload: { referenceId: referenceId }
 };
}

public static DOWNLOAD_JOURNALS_SUCCESS = '[Journals] Download as PDF Success';
public downloadJournalsSuccess(blob: Blob): Action {
 return {
   type: JournalActions.DOWNLOAD_JOURNALS_SUCCESS,
   payload: { blob: blob }
 };
}

जर्नल प्रभाव

@Effect() download$ = this.actions$
    .ofType(JournalActions.DOWNLOAD_JOURNALS)
    .switchMap(({payload}) =>
        this._journalApiService.downloadJournal(payload.referenceId)
        .map((blob) => this._actions.downloadJournalsSuccess(blob))
        .catch((err) => handleError(err, this._actions.downloadJournalsFail(err)))
    );

@Effect() downloadJournalSuccess$ = this.actions$
    .ofType(JournalActions.DOWNLOAD_JOURNALS_SUCCESS)
    .map(({payload}) => saveBlobAs(payload.blob, 'journal.pdf'))

पत्रिका सेवा

public downloadJournal(referenceId: string): Observable<any> {
    const url = `${this._config.momentumApi}/api/journals/${referenceId}/download`;
    return this._http.getBlob(url);
}

HTTP सेवा

public getBlob = (url: string): Observable<any> => {
    return this.request({
        method: RequestMethod.Get,
        url: url,
        responseType: ResponseContentType.Blob
    });
};

जर्नल reducer हालांकि यह केवल हमारे आवेदन में उपयोग किए गए सही राज्यों को सेट करता है जो मैं अभी भी इसे पूरा पैटर्न दिखाने के लिए जोड़ना चाहता था।

case JournalActions.DOWNLOAD_JOURNALS: {
  return Object.assign({}, state, <IJournalState>{ downloading: true, hasValidationErrors: false, errors: [] });
}

case JournalActions.DOWNLOAD_JOURNALS_SUCCESS: {
  return Object.assign({}, state, <IJournalState>{ downloading: false, hasValidationErrors: false, errors: [] });
}

मुझे आशा है कि यह मददगार है।


7

मैं उस समाधान को साझा करता हूं जिसने मेरी मदद की (किसी भी सुधार की बहुत सराहना की गई है)

आपकी सेवा 'pservice' पर:

getMyFileFromBackend(typeName: string): Observable<any>{
    let param = new URLSearchParams();
    param.set('type', typeName);
    // setting 'responseType: 2' tells angular that you are loading an arraybuffer
    return this.http.get(http://MYSITE/API/FILEIMPORT, {search: params, responseType: 2})
            .map(res => res.text())
            .catch((error:any) => Observable.throw(error || 'Server error'));
}

घटक भाग:

downloadfile(type: string){
   this.pservice.getMyFileFromBackend(typename).subscribe(
                    res => this.extractData(res),
                    (error:any) => Observable.throw(error || 'Server error')
                );
}

extractData(res: string){
    // transforme response to blob
    let myBlob: Blob = new Blob([res], {type: 'application/vnd.oasis.opendocument.spreadsheet'}); // replace the type by whatever type is your response

    var fileURL = URL.createObjectURL(myBlob);
    // Cross your fingers at this point and pray whatever you're used to pray
    window.open(fileURL);
}

घटक भाग पर, आप किसी प्रतिक्रिया के लिए सदस्यता के बिना सेवा कहते हैं। ओपनऑफिस माइम प्रकारों की पूरी सूची के लिए सदस्यता देखें: http://www.openoffice.org/framework/documentation/mimetypes/mimetypes.html


7

बेहतर होगा कि आप अपने अंदर की नई पद्धति को बुलाने की कोशिश करें subscribe

this._reportService.getReport()
    .subscribe((data: any) => {
        this.downloadFile(data);
    },
        (error: any) => сonsole.log(error),
        () => console.log('Complete')
    );

downloadFile(data)समारोह के अंदर हमें बनाने की जरूरत हैblock, link, href and file name

downloadFile(data: any, type: number, name: string) {
    const blob = new Blob([data], {type: 'text/csv'});
    const dataURL = window.URL.createObjectURL(blob);

    // IE doesn't allow using a blob object directly as link href
    // instead it is necessary to use msSaveOrOpenBlob
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
      window.navigator.msSaveOrOpenBlob(blob);
      return;
    }

    const link = document.createElement('a');
    link.href = dataURL;
    link.download = 'export file.csv';
    link.click();

    setTimeout(() => {

      // For Firefox it is necessary to delay revoking the ObjectURL
      window.URL.revokeObjectURL(dataURL);
      }, 100);
    }
}

5

पीडीएफ फाइलों को डाउनलोड करने और दिखाने के लिए , एक बहुत ही समान कोड नीचे दिया गया है:

  private downloadFile(data: Response): void {
    let blob = new Blob([data.blob()], { type: "application/pdf" });
    let url = window.URL.createObjectURL(blob);
    window.open(url);
  }

  public showFile(fileEndpointPath: string): void {
    let reqOpt: RequestOptions = this.getAcmOptions();  //  getAcmOptions is our helper method. Change this line according to request headers you need.
    reqOpt.responseType = ResponseContentType.Blob;
    this.http
      .get(fileEndpointPath, reqOpt)
      .subscribe(
        data => this.downloadFile(data),
        error => alert("Error downloading file!"),
        () => console.log("OK!")
      );
  }

5

यहाँ कुछ मैंने अपने मामले में किया है -

// service method
downloadFiles(vendorName, fileName) {
    return this.http.get(this.appconstants.filesDownloadUrl, { params: { vendorName: vendorName, fileName: fileName }, responseType: 'arraybuffer' }).map((res: ArrayBuffer) => { return res; })
        .catch((error: any) => _throw('Server error: ' + error));
}

// a controller function which actually downloads the file
saveData(data, fileName) {
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    let blob = new Blob([data], { type: "octet/stream" }),
        url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = fileName;
    a.click();
    window.URL.revokeObjectURL(url);
}

// a controller function to be called on requesting a download
downloadFiles() {
    this.service.downloadFiles(this.vendorName, this.fileName).subscribe(data => this.saveData(data, this.fileName), error => console.log("Error downloading the file."),
        () => console.info("OK"));
}

समाधान को यहां से संदर्भित किया गया है


4

चरण 2 के लिए फ़ाइल-सेवर और HttpClient का उपयोग करके हेक्टर के उत्तर को अपडेट करें:

public downloadFile(file: File): Observable<Blob> {
    return this.http.get(file.fullPath, {responseType: 'blob'})
}

3

मुझे भ्रष्ट होने के बिना कोणीय 2 से डाउनलोड करने के लिए एक समाधान मिला, वसंत mvc और कोणीय 2 का उपयोग करके

पहला- मेरा रिटर्न टाइप है: - ResponseEntity जावा एंड से । यहाँ मैं बाइट भेज रहा हूँ [] सरणी नियंत्रक से वापसी प्रकार है।

२- अपने कार्यक्षेत्र में फाइलसेवर को शामिल करने के लिए सूचकांक पृष्ठ में निम्नानुसार है:

<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js"></script>

3-घटक ts पर यह कोड लिखें:

import {ResponseContentType} from '@angular.core';

let headers = new Headers({ 'Content-Type': 'application/json', 'MyApp-Application' : 'AppName', 'Accept': 'application/pdf' });
        let options = new RequestOptions({ headers: headers, responseType: ResponseContentType.Blob });
            this.http
            .post('/project/test/export',
                    somevalue,options)
              .subscribe(data => {

                  var mediaType = 'application/vnd.ms-excel';
                  let blob: Blob = data.blob();
                    window['saveAs'](blob, 'sample.xls');

                });

यह आपको xls फाइल फॉर्मेट देगा। यदि आप चाहते हैं कि अन्य प्रारूप सही एक्सटेंशन के साथ मीडियोटाइप और फ़ाइल नाम बदलें।


3

मैं आज इसी मामले का सामना कर रहा था, मुझे एक अटैचमेंट के रूप में एक पीडीएफ फाइल डाउनलोड करनी थी (फाइल को ब्राउजर में रेंडर नहीं किया जाना चाहिए, बल्कि इसके बजाय डाउनलोड किया जाना चाहिए)। यह प्राप्त करने के लिए कि मुझे पता चला कि मुझे एक कोणीय में फ़ाइल प्राप्त करनी थी Blob, और, उसी समय, एक जोड़ेंContent-Disposition प्रतिक्रिया में हेडर ।

यह मेरे लिए सबसे सरल था (कोणीय 7):

सेवा के अंदर:

getFile(id: String): Observable<HttpResponse<Blob>> {
  return this.http.get(`./file/${id}`, {responseType: 'blob', observe: 'response'});
}

फिर, जब मुझे एक घटक में फ़ाइल डाउनलोड करने की आवश्यकता होती है, तो मैं बस कर सकता हूं:

fileService.getFile('123').subscribe((file: HttpResponse<Blob>) => window.location.href = file.url);

अपडेट करें:

अनावश्यक हेडर सेटिंग को सेवा से हटा दिया गया


अगर मैं window.location.href का उपयोग करता हूं तो window.open Chrome इसे कई फ़ाइल डाउनलोड के रूप में मानता है।
डैनो

यह काम नहीं करेगा यदि आपके पास हेडर में जरूरी टोकन हों
garg10may

3

निम्नलिखित कोड ने मेरे लिए काम किया

let link = document.createElement('a');
link.href = data.fileurl; //data is object received as response
link.download = data.fileurl.substr(data.fileurl.lastIndexOf('/') + 1);
link.click();

2

मुझे जवाब मिला कि अब तक अंतर्दृष्टि के साथ-साथ चेतावनियों का भी अभाव है। आप IE10 + (यदि आप परवाह करते हैं) के साथ असंगति के लिए देख सकते हैं और चाहिए।

यह आवेदन भाग और सेवा भाग के बाद का पूरा उदाहरण है। ध्यान दें कि हम फ़ाइलनाम के हेडर को पकड़ने के लिए अवलोकन: "प्रतिक्रिया" सेट करते हैं । यह भी ध्यान दें कि कंटेंट-डिस्पोजल हेडर को सर्वर द्वारा सेट और एक्सपोज करना पड़ता है, अन्यथा वर्तमान कोणीय HttpClient उस पर पास नहीं होगा। मैंने उसके लिए नीचे एक डॉटनेट कोर कोड जोड़ा ।

public exportAsExcelFile(dataId: InputData) {
    return this.http.get(this.apiUrl + `event/export/${event.id}`, {
        responseType: "blob",
        observe: "response"
    }).pipe(
        tap(response => {
            this.downloadFile(response.body, this.parseFilename(response.headers.get('Content-Disposition')));
        })
    );
}

private downloadFile(data: Blob, filename: string) {
    const blob = new Blob([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8;'});
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
    } else {
        const link = document.createElement('a');
        if (link.download !== undefined) {
            // Browsers that support HTML5 download attribute
            const url = URL.createObjectURL(blob);
            link.setAttribute('href', url);
            link.setAttribute('download', filename);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
}

private parseFilename(contentDisposition): string {
    if (!contentDisposition) return null;
    let matches = /filename="(.*?)"/g.exec(contentDisposition);

    return matches && matches.length > 1 ? matches[1] : null;
}

डॉटनेट कोर, कंटेंट-डिस्पोजल और मीडिया टाइप के साथ

 private object ConvertFileResponse(ExcelOutputDto excelOutput)
    {
        if (excelOutput != null)
        {
            ContentDisposition contentDisposition = new ContentDisposition
            {
                FileName = excelOutput.FileName.Contains(_excelExportService.XlsxExtension) ? excelOutput.FileName : "TeamsiteExport.xlsx",
                Inline = false
            };
            Response.Headers.Add("Access-Control-Expose-Headers", "Content-Disposition");
            Response.Headers.Add("Content-Disposition", contentDisposition.ToString());
            return File(excelOutput.ExcelSheet, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        }
        else
        {
            throw new UserFriendlyException("The excel output was empty due to no events.");
        }
    }

1
 let headers = new Headers({
                'Content-Type': 'application/json',
                'MyApp-Application': 'AppName',
                'Accept': 'application/vnd.ms-excel'
            });
            let options = new RequestOptions({
                headers: headers,
                responseType: ResponseContentType.Blob
            });


this.http.post(this.urlName + '/services/exportNewUpc', localStorageValue, options)
                .subscribe(data => {
                    if (navigator.appVersion.toString().indexOf('.NET') > 0)
                    window.navigator.msSaveBlob(data.blob(), "Export_NewUPC-Items_" + this.selectedcategory + "_" + this.retailname +"_Report_"+this.myDate+".xlsx");

                    else {
                        var a = document.createElement("a");
                        a.href = URL.createObjectURL(data.blob());
                        a.download = "Export_NewUPC-Items_" + this.selectedcategory + "_" + this.retailname +"_Report_"+this.myDate+ ".xlsx";
                        a.click();
                    }
                    this.ui_loader = false;
                    this.selectedexport = 0;
                }, error => {
                    console.log(error.json());
                    this.ui_loader = false;
                    document.getElementById("exceptionerror").click();
                });

1

बस नीचे के urlरूप hrefमें डाल दिया ।

<a href="my_url">Download File</a>

क्या यह काम करता है? मुझे त्रुटि मिली ... "ERROR TypeError:" Access to 'file: ///Downloads/test.json' स्क्रिप्ट से इनकार किया। ""
Jay

धन्यवाद u pls साझा कर सकते हैं कि ur url कैसा दिखता है? यह फ़ाइल प्रोटोकॉल या http या कुछ और?
Jay

यह फ़ाइल प्रोटोकॉल है।
हरुनूर रशीद

1

<a href="my_url" download="myfilename">Download file</a>

my_url की उत्पत्ति समान होनी चाहिए, अन्यथा यह उस स्थान पर रीडायरेक्ट हो जाएगी


हां, यह शुद्ध html के लिए काम करेगा, यह सुनिश्चित नहीं है कि अन्य जटिल सामानों की तलाश क्यों की जाए
VIVEK SINGH


1

आप अपने टेम्पलेट से सीधे एक फ़ाइल डाउनलोड कर सकते हैं जहाँ आप डाउनलोड विशेषता का उपयोग [attr.href]करते हैं और आप घटक से एक संपत्ति मूल्य प्रदान कर सकते हैं। यह सरल समाधान अधिकांश ब्राउज़रों पर काम करना चाहिए।

<a download [attr.href]="yourDownloadLink"></a>

संदर्भ: https://www.w3schools.com/tags/att_a_download.asp


1
एसओ में आपका स्वागत है! कृपया जांचें कि क्या मेरी (टाइपिंग और व्याकरण) सुधार मददगार हैं।
बी - रियान

0

यदि आप केवल एक URL पर पैरामीटर भेजते हैं, तो आप इसे इस तरह से कर सकते हैं:

downloadfile(runname: string, type: string): string {
   return window.location.href = `${this.files_api + this.title +"/"+ runname + "/?file="+ type}`;
}

पैरामीटर प्राप्त करने वाली सेवा में


0

यह उत्तर बताता है कि आप सीधे AJAX के साथ फाइल डाउनलोड नहीं कर सकते, मुख्य रूप से सुरक्षा कारणों से। तो मैं वर्णन करता हूँ कि मैं इस स्थिति में क्या करता हूँ,

01. फ़ाइल के hrefअंदर अपने एंकर टैग में विशेषता जोड़ें component.html,
जैसे: -

<div>
       <a [href]="fileUrl" mat-raised-button (click)='getGenaratedLetterTemplate(element)'> GENARATE </a>
</div>

02.component.ts सुरक्षा स्तर को दरकिनार करने के लिए अपने सभी निम्न चरणों का पालन करें और सहेजें को पॉपअप संवाद के रूप में लाएँ,
जैसे: -

import { environment } from 'environments/environment';
import { DomSanitizer } from '@angular/platform-browser';
export class ViewHrApprovalComponent implements OnInit {
private apiUrl = environment.apiUrl;
  fileUrl
 constructor(
    private sanitizer: DomSanitizer,
    private letterService: LetterService) {}
getGenaratedLetterTemplate(letter) {

    this.data.getGenaratedLetterTemplate(letter.letterId).subscribe(
      // cannot download files directly with AJAX, primarily for security reasons);
    console.log(this.apiUrl + 'getGeneratedLetter/' + letter.letterId);
    this.fileUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.apiUrl + 'getGeneratedLetter/' + letter.letterId);
  }

नोट: यदि आप स्थिति कोड 200 के साथ "ओके" त्रुटि प्राप्त कर रहे हैं तो यह उत्तर काम करेगा


0

ठीक है, मैंने उपरोक्त कई उत्तरों से प्रेरित कोड का एक टुकड़ा लिखा है जो आसानी से अधिकांश परिदृश्यों में काम करना चाहिए जहां सर्वर किसी भी तृतीय-पक्ष प्रतिष्ठानों के बिना, rxjs और कोणीय को छोड़कर, एक सामग्री वितरण हेडर के साथ एक फ़ाइल भेजता है।

सबसे पहले, अपने घटक फ़ाइल से कोड को कैसे कॉल करें

this.httpclient.get(
   `${myBackend}`,
   {
      observe: 'response',
      responseType: 'blob'
   }
).pipe(first())
.subscribe(response => SaveFileResponse(response, 'Custom File Name.extension'));

जैसा कि आप देख सकते हैं, यह मूल रूप से दो बदलावों के साथ कोणीय से औसत बैकएंड कॉल है

  1. मैं शरीर के बजाय प्रतिक्रिया देख रहा हूं
  2. मुझे प्रतिक्रिया के बारे में स्पष्ट रूप से कहा जा रहा है

एक बार फ़ाइल सर्वर से लाए जाने के बाद, मैं सिद्धांत रूप में हूं, फ़ाइल को हेल्पर फ़ंक्शन में सहेजने के पूरे कार्य को सौंपता हूं, जिसे मैं एक अलग फ़ाइल में रखता हूं, और जो भी घटक मुझे चाहिए, उसमें आयात करें

export const SaveFileResponse = 
(response: HttpResponse<Blob>, 
 filename: string = null) => 
{
    //null-checks, just because :P
    if (response == null || response.body == null)
        return;

    let serverProvidesName: boolean = true;
    if (filename != null)
        serverProvidesName = false;

    //assuming the header is something like
    //content-disposition: attachment; filename=TestDownload.xlsx; filename*=UTF-8''TestDownload.xlsx
    if (serverProvidesName)
        try {
            let f: string = response.headers.get('content-disposition').split(';')[1];
            if (f.includes('filename='))
                filename = f.substring(10);
        }
        catch { }
    SaveFile(response.body, filename);
}

//Create an anchor element, attach file to it, and
//programmatically click it. 
export const SaveFile = (blobfile: Blob, filename: string = null) => {
    const a = document.createElement('a');
    a.href = window.URL.createObjectURL(blobfile);
    a.download = filename;
    a.click();
}

वहाँ, कोई और अधिक गूढ़ GUID फ़ाइल नाम! सर्वर में जो भी नाम दिया गया है, उसका उपयोग हम क्लाइंट में स्पष्ट रूप से निर्दिष्ट किए बिना कर सकते हैं, या सर्वर द्वारा प्रदान किए गए फ़ाइलनाम को ओवरराइट कर सकते हैं (जैसा कि इस उदाहरण में)। इसके अलावा, कोई भी आसानी से जरूरत पड़ने पर अपनी आवश्यकताओं के अनुरूप सामग्री-स्वभाव से फ़ाइल नाम निकालने के एल्गोरिदम को बदल सकता है, और बाकी सब कुछ अप्रभावित रहेगा - इस तरह के निष्कर्षण के दौरान त्रुटि के मामले में, यह सिर्फ 'अशक्त' हो जाएगा फ़ाइल नाम के रूप में।

जैसा कि एक और जवाब पहले से ही बताया गया है, IE को हमेशा की तरह कुछ विशेष उपचार की आवश्यकता होती है। लेकिन कुछ महीनों में क्रोमियम बढ़त के साथ, मैं इस बारे में चिंता नहीं करूंगा कि नए ऐप (उम्मीद) बनाए जा रहे हैं। URL को निरस्त करने की बात भी है, लेकिन मैं इसके बारे में निश्चित नहीं हूं, इसलिए यदि कोई टिप्पणी में इसके साथ मदद कर सकता है, तो यह बहुत बढ़िया होगा।


0

यदि कोई टैब बिना कुछ डाउनलोड किए खुलता और बंद होता है, तो मैंने नकली एंकर लिंक का अनुसरण करने की कोशिश की और यह काम कर गया।

downloadFile(x: any) {
var newBlob = new Blob([x], { type: "application/octet-stream" });

    // IE doesn't allow using a blob object directly as link href
    // instead it is necessary to use msSaveOrOpenBlob
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
      window.navigator.msSaveOrOpenBlob(newBlob);
      return;
    }

    // For other browsers: 
    // Create a link pointing to the ObjectURL containing the blob.
    const data = window.URL.createObjectURL(newBlob);

    var link = document.createElement('a');
    link.href = data;
    link.download = "mapped.xlsx";
    // this is necessary as link.click() does not work on the latest firefox
    link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));

    setTimeout(function () {
      // For Firefox it is necessary to delay revoking the ObjectURL
      window.URL.revokeObjectURL(data);
      link.remove();
    }, 100);  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.