Im using the filesaver js library for download files... i'm generating a endpoint with web api that returns my file from base64 but i don't know how to return base64 as Blob for download with filesaver....
Im tried make differents responses types
try to understand how to does it works the Blob data
public HttpResponseMessage GetFile(int id)
{
string mybase64file = GetBase64File(id)
byte[] bytes = Convert.FromBase64String(mybase64file );
MemoryStream ms = new MemoryStream(bytes);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(ms);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "someFileName.pdf";
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return result;
}
AngularJS service:
function download() {
var deferred = $q.defer()
$http.get('url', {
headers: {
'Content-type': 'application/octet-stream',
},
responseType: 'blob'
})
.success(function (response) {
saveAs(response, 'someName.pdf')
})
.error(function (err) {
deferred.reject(err)
})
return deferred.promise
}
When the angularjs service recieve to response, im call the "saveAs" function, but this generate the next error:
"angular.min.js:118 TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided."
To return a file from ASP MVC CORE, use:
return File(stream, "application/octet-stream");
return FileStreamResult(stream, "application/octet-stream");
return PhysicalFileResult("path to file", "application/octet-stream");
With that, you dont even need filesaver js library, the file will download automatically once that link is requested.
One more thing: You cant download a file with Ajax (....$http.get('url', {....)!
You could use Fetch API do get the blob, see implementation here: https://stackoverflow.com/a/9970672/3563013
To address the specific error ( "angular.min.js:118 TypeError: Failed to execute 'createObjectURL' on 'URL': No function was found that matched the signature provided." ), its possible window.URL.createObjectURL is not supported in the browser you are using to test.
Related
Server Side
I trying to send file from NodeJs
/**
* Exports data to PDF format route.
*/
app.post('/export/pdf', upload.single('imageBlob'), function (request, response) {
var PDF = require('./services/PdfService').PDF;
var fileUrl = PDF.generatePDFExport(request.body, request.file.buffer);
setTimeout(() => {
response.sendFile(fileUrl);
}, 200);
});
This piece of code creates a valid pdf file (I can open it browsers URL hit file)
But some browser hides the pop-up window and I wanted to download a file instead of opening it.
I check response in client and it is some BLOB looking response.
Client Side
I try to create a file from the response but there is only an empty pdf file.
return axios.post('http://172.18.0.2:8001/export/pdf', formData).then(response => {
let blob = new Blob([response.data]);
FileSaver.saveAs(blob, "st-seatmap-shop.pdf");
})
What is a mistake here? On the server side with a sending file or on the client with saving file?
The only problem was in sending a request to the server.
Server by default returns stream and for saving file on client response needs to be a BLOB so I just updated request.
let requestOptions = {
responseType: 'blob'
};
return axios.post('http://172.18.0.2:8001/export/pdf', formData, requestOptions).then(response => {
let blob = new Blob([response.data]);
FileSaver.saveAs(blob, "st-seatmap-shop.pdf");
}).catch(error => {
console.log("error.response is : ", error);
});
Receiving HTTP Failure during parsing in Angular. Goal is to download a csv file from the api response
Controller:
downloadFile(data) {
const blob = new Blob([data], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
window.open(url);
}
getFileDownload(): void {
this.iportalUploadService.getFileDownload(this.fileName).subscribe(data => {
debugger;
this.fileDownload = data;
this.downloadFile(data);
});
}
Service:
private fileDownloadUrl = 'file-transfer/validationErrorsCSV';
formHtppOptions(params): any {
const httpOptions = {
headers: { 'Application-Token': this.getToken() },
params: params,
};
return httpOptions;
}
getFileDownload(fileName): Observable < Object > {
const baseUrl = this.getBaseUrl();
return this.http.get<Object>(baseUrl + this.fileDownloadUrl, this.formHtppOptions({ fileName: fileName }));
}
Below is the console error I am receiving
console error
Response format Photo
Response photo
You are getting this error because your response is not in JSON format. You are trying to convert it into an object and CSV text cannot be parsed to a proper json object. Here is what you might want to do:
getFileDownload(fileName): Observable<any> {
const baseUrl = this.getBaseUrl();
return this.http.get(baseUrl + this.fileDownloadUrl, this.formHtppOptions({fileName: fileName})).pipe(map((data:any) => this.converter.ToJson(data)));
}
Usually, I have a "converter" service that does this kind of parsing. You can make use of papa parse, or parse yourself by looping through the response.
Update: Here is an example of manually parsing the response: http://blog.sodhanalibrary.com/2016/10/read-csv-data-using-angular-2.html
Have a look at the above blog post.
I resolved this issue by adding responseType: 'text' in formhttpOtions.
Below is the detail of JAVA rest service which downloads a file from server:
Method prototype:
#POST
#Path("/prop/export")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
#Consumes(MediaType.APPLICATION_JSON)
public Response exportItemsToFile(Map<String, String> params);
The Response is build from byte array in its implementation:
Response.ok(someByteArray)
I am using FileSaver.saveAs to download the response in a xls file using below code
var requestUri = '/wtk/rc/v1/pfm/prop/export';
var payload={"context":addCtx,"language":addLang,"country":addCountry,"swimlane":addSL};
$http.post(requestUri, payload, {
headers: {
'Content-Type': 'application/json'
},
responseType: 'arraybuffer',
}).success(function (data) {
var blob = new Blob([data],{type : 'application/vnd.ms-excel'});
var fileName = addLang+"_"+addCountry+".xls";
filesaver.saveAs(blob,fileName);
}).error(function () {
//download failed
});
The response which is xls file is corrupt using the above code. **
It is because the promise returned by $http.post have blank response
in case of if rest client produces octet-stream
**
But if I use some rest client like Postman, and select "Send and Download" option and save the response as xls. It is coming up fine.
Any help in this will be appreciated.
I am trying to use an API to update a list on another server using node.js. For my last step, I need to send a POST that contains a csv file. In the API, they list under FormData that I need a Key called file and a Value of Binary Upload, then the body of the request should be made of listname: name and file: FileUpload.
function addList(token, path, callback) {
//Define FormData and fs
var FormData = require('form-data');
var fs = require('fs');
//Define request headers.
headers = {
'X-Gatekeeper-SessionToken': token,
'Accept': 'application/json',
'Content-Type': 'multipart/form-data'
};
//Build request.
options = {
method: 'POST',
uri: '{URL given by API}',
json: true,
headers: headers
};
//Make http request.
req(
options,
function (error, response, body) {
//Error handling.
if (error) { callback(new Error('Something bad happened')); }
json = JSON.parse(JSON.stringify(response));
callback.call(json);
}
);
//Attempt to create form and send through request
var form = new FormData();
form.append('listname', 'TEST LIST');
form.append('file', fs.createReadStream(path, { encoding: 'binary' }));
form.pipe(req);};
I am a veteran of front end javascript for html and css, but this is my first adventure with backend node.js. The error I keep getting is: TypeError: dest.on is not a function
From what I can tell, this has to do with the way I used form.pipe(req) but I can't find documentation telling me the appropriate usage. If you don't have a direct answer, a finger pointing toward the right documentation would be appreciated.
The issue is you're not passing the request instance into your pipe call, you're passing the request module itself. Take a reference to the return value of your req(...) call and pass this instead i.e.
//Make http request.
const reqInst = req(
options,
function (error, response, body) {
//Error handling.
if (error) { callback(new Error('Something bad happened')); }
json = JSON.parse(JSON.stringify(response));
callback.call(json);
}
);
//Attempt to create form and send through request
var form = new FormData();
...
form.pipe(reqInst);
This line:
.pipe(fileinclude)
Should be this:
.pipe(fileinclude())
from
why am i getting this error? dest.on is not a function - using gulp-file-include
I have tried a myriad of different function calls, but can't seem to figure out how to trigger a download for a CSV in EmberJs.
Here is my latest code:
let endpoint = '/api/foo/';
let options = {
url: endpoint,
type: 'POST',
data: {},
dataType: 'text'
};
return new Ember.RSVP.Promise((resolve, reject) => {
options.success = function(result) {
var uri = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(result);
window.open(uri, 'foo.csv');
};
options.error = (xhr, errorThrown) => {
console.log('error');
// return Ember.run(null, reject, this.didError(xhr, xhr.status, xhr.responseJSON, 1));
};
Ember.$.ajax(options);
});
This code doesn't raise any server or client side errors. It's getting a 200 response. No javascript errors, and doesn't console log anything, so I know it's not hitting the error block. But... it won't trigger the file download on the client. Does anyone know what is missing?
I am unable to test this, but I believe your issue is with returning a new promise, whereas what you really want is to return the promise itself.
So change your code to:
let endpoint = '/api/foo/';
let options = {
url: endpoint,
type: 'POST',
data: {},
dataType: 'text'
};
return Ember.RSVP.Promise((resolve, reject) => { // note the deletion of new
options.success = function(result) {
var uri = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(result);
window.open(uri, 'foo.csv');
};
options.error = (xhr, errorThrown) => {
console.log('error');
// return Ember.run(null, reject, this.didError(xhr, xhr.status, xhr.responseJSON, 1));
};
Ember.$.ajax(options);
});
In implementing a similar piece of functionality, I went for a different route. Rather than creating an AJAX request, I create a form and submit it to the server. My API endpoint will then return the CSV in the response, with the appropriate Content-Disposition headers, and the browser will just download the file.
(Depending on your authentication scheme, you may have to include your authentication token as a value in your form data).
Example code below. You'll see I'm adding the auth token. The form's action URL is set in the markup of the page, but you could set it dynamically here if you wanted.
csvDownload () {
let form = Ember.$('#csvdownloadform')
let input = Ember.$('#csvdownloadtoken')
input.val(this.get('session').get('session.content.authenticated.token'))
form.submit()
input.val('')
form_func.val('')
},