VueJs/Axios - Download pdf file in browser from API call - vue.js

I am trying to download an pdf file using VueJs/Axios, but I get an empty file. The stream is 111 kb when created in C# but only 300 bytes when returned to Vue.js.
C#
HttpResponseMessage httpResponse = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
httpResponse.Content = new StreamContent(ms);
httpResponse.Content.Headers.ContentDisposition = new
System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
httpResponse.Content.Headers.ContentDisposition.FileName = "test";
httpResponse.Content.Headers.ContentType = new
System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
return httpResponse;
Vue.js
createPdf: function () {
var self = this;
self.ShowSpinner = true;
axios({
method: 'post',
url: self.baseUrl + '/api/ChangeRequestReport/CreatePdf',
responseType: 'blob',
data: {
model: self.ChangeRequestReportModel
}
})
.then(function (response) {
console.log(response);
//self.ChangeRequestReportModel = response.data;
const url = window.URL.createObjectURL(new Blob([response.data], { type: "application/pdf" }));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'test.pdf'); //or any other extension
document.body.appendChild(link);
link.click();
self.ShowSpinner = false;
})
.catch(error => {
console.log(error);
this.error = true;
alert("error");
});

Related

Upload Image With Expo & Fetch

I am trying to upload an image from my react native app.
If I use my local node server and run this code:
var fs = require("fs");
var options = {
method: "POST",
url: "my_URL",
headers: {},
formData: {
file: {
value: fs.createReadStream("../../assets/image.png"),
options: {
filename: "image.jpg",
contentType: null
}
}
}
};
request(options, function (error, response) {
if (error) throw new Error(error);
console.log(response.body);
});
I have a succesful upload.
However, with the URI from that we get through the the app, it does not work:
Here is my code on React Native Expo:
const body = new FormData();
body.append("file", 'file:///path/to/file/image123.jpg');
fetch(url, {
method: "POST",
body,
headers: {
"content-type": "multipart/form-data"
}
})
.then(response => {
console.log(response, "RESPONSE");
})
.then(result => {
console.log(result, "RESULT");
})
.catch(error => {
console.log(error, "ERROR");
});
I am unable to get it to work. I think it has something to do with the file path from the device.
Any help will be appreciated.
try to create FormData using this function
const createFormData = (uri) => {
const fileName = uri.split('/').pop();
const fileType = fileName.split('.').pop();
const formData = new FormData();
formData.append('file', {
uri,
name: fileName,
type: `image/${fileType}`
});
return formData;
}
if it doesn't work check permissions

uploading files to endpoint from a static webpage

I am trying to upload files to an S3 endpoint from a static HTML page but the files are always malformed when I download them from the bucket. The relevant code is below - what am I doing wrong with fetch?
const onSubmitForm = function (e) {
const file = this.files[0];
const reader = new FileReader();
// reader.readAsText(file); // didn't work
reader.readAsDataURL(file); // also didn't work
reader.onload = async function () {
const bodyData = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
file: {
// the backend endpoint expects a base64 encoded img
// the upload completes but the
"data": reader.result.toString()
},
"name": file.name
})
}
const response = await fetch(uploadUrl, bodyData).then(
res => res.json()
);
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
//
}

Problem to generate pdf from a blob in an expo app using FileSystem

I get a blob and I treat it like this:
const file = response.data;
var blob = new Blob([file], {
type: 'application/pdf',
});
const fileReaderInstance = new FileReader();
fileReaderInstance.readAsDataURL(blob);
fileReaderInstance.onload = async () => {
const fileUri = `${FileSystem.documentDirectory}file.pdf`;
await FileSystem.writeAsStringAsync(
fileUri,
fileReaderInstance.result.split(',')[1],
{
encoding: FileSystem.EncodingType.Base64,
}
);
console.log(fileUri);
Sharing.shareAsync(fileUri);
};
however when I generate and share the file, I can't access it and if I get its URI and search on the web it returns:
i solved my problem in this way:
This is a func who get other data to request, do the request (generate PDF()) and treat the data and generate by received blob the buffer on (fileReaderInstance.result) who is shared in Sharing.shareAsync()
const generatePDF = async () => {
setAnimating(true);
const companyReponse = await CompanyService.getCompany();
const peopleResponse = await PeopleService.getPerson(sale.customerId);
const company = companyReponse.response.company;
const people = peopleResponse.response;
const quote = false;
const json = await SaleService.generatePDF({
sale,
company,
people,
quote,
});
if (json && json.success) {
try {
const fileReaderInstance = new FileReader();
fileReaderInstance.readAsDataURL(json.data);
fileReaderInstance.onload = async () => {
const base64data = fileReaderInstance.result.split(',');
const pdfBuffer = base64data[1];
const path = `${FileSystem.documentDirectory}/${sale._id}.pdf`;
await FileSystem.writeAsStringAsync(`${path}`, pdfBuffer, {
encoding: FileSystem.EncodingType.Base64,
});
await Sharing.shareAsync(path, { mimeType: 'application/pdf' });
};
} catch (error) {
Alert.alert('Erro ao gerar o PDF', error.message);
}
}
setAnimating(false);
}
This is the func in SaleServicegeneratePDF who do the request to api and pass the parameters that return a blob of pdf using axios:
generatePDF: async ({ sale, company, people, quote }) => {
const token = await AsyncStorage.getItem('token');
const body = { sale, company, people, quote };
try {
const response = await axios(`${BASE_API}/generate-sale-pdf`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: token,
},
responseType: 'blob',
data: body,
});
return {
success: true,
data: response.data,
};
} catch (err) {
return err.error;
}
},
I have solved this problem by passing the blob string to WriteAsStringAsync method of FileSystem library from expo.
const blobDat = data.data[0].data; //blob data coming from an API call
const fileUri = FileSystem.documentDirectory + `testt.pdf`; //Directory Link of the file to be saved
await FileSystem.writeAsStringAsync(fileUri, blobDat, {
encoding: FileSystem.EncodingType.UTF8,
}) //This step writes the blob string to the pdf fileURI
await IntentLauncher.startActivityAsync("android.intent.action.VIEW", {
data: fileUri,
flags: 1,
type: "application/pdf",
});
//prompts user with available application to open the above created pdf.

In Nodejs/Express js i am unable to return response to Angular 6

I am using Angular 6 and Nodejs/Expressjs to avoid cross domain issue. So here is my code
In Angular i am calling:
this.httpClient.post('/uploadFile', formData, {params: params})
.pipe(map((res: any) => {return res}),
catchError((error: HttpErrorResponse) => {})
Nodejs/Expressjs:
app.post('/uploadFile', (req, res) => {
let formData
const form = new IncomingForm();
let readStream;
form.on('file', (field, file) => {
console.log('file.path>>>',file.path);
readStream = fs.createReadStream(file.path);
});
form.on ('fileBegin', function(name, file) {
//rename the incoming file to the file's name
let fileName = file.path.split("\\");
fileName[fileName.length-1] = file.name.split('.')[0];
fileName = fileName.join("\\");
file.path = fileName;
console.log('file.path', file.path);
console.log('file.name', file.name);
})
form.parse(req, function (err, fields, files) {
formData = new FormData();
formData.append("file", readStream);
formData.append('package_name', req.query.packagename);
formData.append('type', req.query.type);
formData.append('version', req.query.version);
formData.append('descr', req.query.descr);
console.log('req.query.packagename',req.query.packagename);
const axiosConfig = {
headers: {
'Content-Type': 'multipart/form-data'
}
};
let uploadRequest = request.post("WebAPiCallURL", requestCallback);
uploadRequest._form = formData;
uploadRequest.setHeader('Content-Type', 'multipart/form-data');
function requestCallback(err, res, body) {
return JSON.parse(body);
}
});
});
From requestCallback i am unable to send response to Angular6
Your not sending response from to the client. To send you can use res.send or any of the response function from Expressjs.
function requestCallback(err, response, body) { //Rename res to response to avoid conflict
res.send(body); // Send Response to Client
}
Note : As you used same variable res for request, Rename to some other name

AWS S3 Signature Does Not Match

I am stuck on s3.getSignedUrl and getting the error 'Signature Does Not Match, Signature calculated does not match...'. I have checked the credentials, and so many other things, but am not making any progress. I have my access key and secret saved in a credentials file.
The URL I'm getting back is https://postcard-photo-repo-dev.s3.amazonaws.com/Screenshot7.png?AWSAccessKeyId=AKIAJWHTSREEZUZGGO3A&Expires=1534619652&Signature=MkyVjARuo3PaO6lAYV6Li%2FAaR9E%3D
upload.js file:
function getSignedRequest(file) {
const xhr = new XMLHttpRequest();
xhr.open('GET', `/api/feed/sign-s3?file-name=${file.name}&file-type=${file.type}`);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4){
if(xhr.status === 200){
const response = JSON.parse(xhr.responseText);
uploadFile(file, response.signedRequest, response.url);
} else {
alert('Could not get signed URL');
}
}
};
xhr.send();
}
function uploadFile(file, signedRequest, url){
const xhr = new XMLHttpRequest();
xhr.open('PUT', signedRequest);
xhr.onreadystatechange = () => {
if(xhr.readyState === 4) {
if(xhr.status === 200) {
$('#preview').src = url;
$('#avatar-url').value = url;
} else {
alert('Could not upload file');
}
}
};
xhr.send(file);
}
routes file:
router.get('/sign-s3', (req, res) => {
const s3 = new aws.S3();
const fileName = req.query['file-name'];
const fileType = req.query['file-type'];
const s3Params = {
Bucket: S3_BUCKET,
Key: fileName,
Expires: 600,
// ACL: 'public-read',
// ContentType: fileType
};
s3.getSignedUrl('putObject', s3Params, (err, data) => {
if(err) {
console.log(err);
return res.end();
}
console.log(data);
const returnData = {
signedRequest: data,
url: `https://${S3_BUCKET}.s3.amazonaws.com/${fileName}`
};
res.write(JSON.stringify(returnData));
res.end();
});
});