Issue
i am struggling to get this stream downloading file works if i try the same request using curl the stream works fine and streaming the data. in my angular app the file is completely download before the client see the download file tab it seems like the subscribe only happened after all stream body fully downloaded
what i am trying to achive is after first chunk of data send to angular app i want the file to start downloading.
instead after observing the network only after all file downloaded from the backend the downLoadFile methood is called and the ui expirence is stuck
this is a minimal example of what i am trying todo at the backend i have a genrator that genreate a huge file and pipe the request
Node JS
const FILE = './HUGE_FILE.csv'
const lines = await fs.readFileSync(FILE, 'utf8').split('\n')
function* generator() {
for (const i of files) {
console.log(i)
yield i
}
}
app.get('/', async function (req, res) {
res.setHeader('Content-Type', 'text/csv');
res.setHeader('Content-Disposition', 'attachment; filename=\"' + 'download-' + Date.now() + '.csv\"');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Pragma', 'no-cache');
const readable = Readable.from(generator());
readable.pipe(res);
});
at the client side calling the endpoint and waiting for the resonse
Angular code
@Component({
selector: 'is-optimizer-csv',
templateUrl: './optimizer-csv.component.html',
styleUrls: ['./optimizer-csv.component.scss']
})
export class OptimizerCsvComponent implements OnInit {
private onDownloadButtonClicked() {
const data = {...this.form.get('download').value, ...(this.advertiserId ? {advertiserId: this.advertiserId} : null)};
this.loading$.next(true);
this.optimizerService
.downloadOptimizerCsvData(data)
.pipe(
take(1),
tap(_ => this.loading$.next(false))
)
.subscribe();
}
}
@Injectable({
providedIn: 'root'
})
export class OptimizerService {
constructor(private readonly http: Ht, private datePipe: DatePipe) {}
downloadOptimizerCsvData(data: any) {
this.http.get(`${environment.apiUrl}`,{
responseType: 'arraybuffer',headers:headers}
).subscribe(response => this.downLoadFile(response, "text/csv"));
}
downLoadFile(data: any, type: string) {
let blob = new Blob([data], { type: type});
let url = window.URL.createObjectURL(blob);
let pwa = window.open(url);
if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
alert( 'Please disable your Pop-up blocker and try again.');
}
}
}
Solution
it look like angular common http client does not support streaming out of the box .
see this github issue by @prabh-62
https://github.com/angular/angular/issues/44143
from this thread the why to solve your issue is by implementing the fetch stream logic using native fetch
Answered By - Orna Satamker
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.