Manage to download PDF stream with Blob in javascript - javascript

A web page (front) is calling a service which send a PDF stream as a response :
Here is the front code :
'click .btn': function (event) {
/.../
event.preventDefault();
Http.call(params, (err, res) => { // callback
if (err) console.log(err); // nothing
console.log({ res }); // print below result
const blob = new Blob(
[res.content],
{ type: `${res.headers['content-type']};base64` }
);
saveAs(blob, res.headers['content-disposition'].slice(21));
});
}
Here is the response from the server ( console.log(res) ) : { res : Object } printed in the console.
content: "%PDF-1.4↵1 0 obj↵<<↵/Title (��)↵/Creator (��)↵/Prod ..... lot of characters....%"
data: null,
statusCode: 200,
headers: {
connection: "close",
content-disposition: "attachment; filename=myDoc.pdf"
content-type: "application/pdf",
date: "date",
transfer-encoding: "chunked",
x-powered-by: "Express"
}
However, the PDF is downloaded with no content, it's full blank like corrupted ( But I can see the content in the string ). It works well with the CSV routes ( I send a csv as a stream and download it with the same method and I got the data).
I think there is something with the format %PDF ...% but I didn't manage to find something.
Note : With postman, it works, my PDF is saved, the page is not blank, I got the data. So there is something in the front I am not doing right.
I also tried with :
const fileURL = URL.createObjectURL(blob);
window.open(fileURL); // instead of saveAs
but the result is the same ( but in another tab instead of saved PDF ) blank page.
Any ideas ?

You probably forgot to specify the response type in your inital backend call - from the example you posted "arraybuffer" would be the correct one here, you can check all types here.

Related

How to remove Content-Type from multipart/form-data Body Request?

I am trying to upload array of files as multipart/form data.
I use ngx-file-upload v6.0.1
Here is slightly changed method from the library example. I am copying it to show that file is of type File.
public onFileAdded (files: UploadFile[]) {
for (const droppedFile of files) {
if (droppedFile.fileEntry.isFile) {
const fileEntry = droppedFile.fileEntry as FileSystemFileEntry;
fileEntry.file((file: File) => {
this.certificates$.next({
type: ACTIONS.ADD,
value: new Certificate(file, this.getSizeString(file.size), droppedFile.relativePath)
});
});
}
}
Here is onSubmit method:
public submitCertificates(certificates: Certificate[]): Observable<Certificate[]> {
const url = this.completionCertificatesUrl;
const headers = new HttpHeaders({'Content-Type': 'multipart/form-data'});
const formData = new FormData();
certificates.forEach(certificate => {
formData.append('files', certificate.file, certificate.relativePath);
})
return this.http.post<any>(url, formData, {headers}).pipe(
map(data => data)
);
Post request that is sent has following data:
request payload
The problem is that backend (Spring framework which I have no access to and no understanding) throws 500 and does not accept this payload.
I was told that correct payload should look like this:
Content-Type: multipart/form-data; boundary=79ab782d574b45598e6e50d722985144
--79ab782d574b45598e6e50d722985144
Content-Disposition: form-data; name="files"; filename="file-1.json"
content of file-1 file
--79ab782d574b45598e6e50d722985144
Content-Disposition: form-data; name="files"; filename="fil2-2.zip"
content of file-2 file
--79ab782d574b45598e6e50d722985144--
My questions is how can I remove "Content-Type" key from my payload?
I did try a lot of combinations of append(), delete() to no result.
Also, my concern is if the file is really attached to this request. Can I check it anyhow?
I wonder if I am missing the content of the file altogether, because in the example I was provided there is a line "content of file-1" and maybe this is a shortcut for a much longer string that would represent the file content.
Please, help!
My questions is how can I remove "Content-Type" key from my payload?
Look at where you set it:
Delete this line:
const headers = new HttpHeaders({'Content-Type': 'multipart/form-data'});
Delete headers from this line.
return this.http.post<any>(url, formData, {headers}).pipe(

How to upload a file along with text using fetch in react native?

I'm trying to upload a file to the server using react-native-document-picker. The problem I'm facing is I don't know how to upload the file along with a text.In my app there is a portion for file upload also there is an area for writing some text.Then it will get uploaded to the server.So I've done the following.But I'm getting this error after submitting to server
unhandled promise rejection unsupported BodyInit type
updated portion of code
filepick = () => {
DocumentPicker.show({
filetype: [DocumentPickerUtil.images()],
}, (error, res) => {
if (error == null) {
console.log(
res.uri,
res.type, // mime type
res.fileName,
res.fileSize
);
this.setState({
img_uri: res.uri,
img_type: res.type,
img_name: res.fileName
})
} else {
Alert.alert('Message', 'File uploaded failed');
}
});
};
onPressSubmit() {
const data = new FormData();
data.append('file', { uri: this.state.img_uri, type:
this.state.img_type, name: this.state.img_name })
data.append('comment', { text: this.state.text });
AsyncStorage.getItem("userdetail").then(value => {
fetch(GLOBAL.ASSN_URL +`${this.props.id}`, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
'Authorization': value
},
body: data
}).then((response) => {
return response.text()
}).then((responseJson) => {
var result = responseJson;
console.log(result);
});
})
}
The function filepick() is called after choosing a file from your device.Please help me to find a solution.How do I upload this to server also how to send text without stringifying it?
body: ({
file: this.state.file,
comment: this.state.text
})
Why are you wrapping body in brackets? Removing them might fix it.
Also see this, https://github.com/facebook/react-native/issues/6025 you might want to stringify the body object, since your content type is not application/json
body: JSON.stringify({
file: this.state.file,
comment: this.state.text
})
Edit
From comments we now know the following
1) You are uploading a file separately.
2) The upload response contains information about the file
3) You are saving the entity in separate server call
4) You need to save file with that entity
The solution below assumes that you have full control over server and you are also handling the file uploading endpoint. Here is the solution
You basically do not need to upload the whole file again with your entity since it is already uploaded on server, all you need to do is to save the reference of the file with entity. Their are two ways to save the reference
1) Just save either the fileName or fileUrl in your entity table and then store the name or url with entity so it will look like this
{
id: 1,
name: 'Cat',
picture: // url or name of picture
}
2) Save the uploaded file in different table, then save the id of the file with your entity, and when you fetch entities get the related file. However if the relationship between entity and file is one to many as in one entity can have many files then you will first need to save the entity and then upload the files with reference of entity. This way your entity will look like this
{
id: 1,
name: 'Cat',
pictures: [{fileName: 'cat1'}, {fileName: 'cat2'}]
}

Vue-Resource upload file to PHP

I am trying to send an image through a resource and recovery in a php file but I have not succeeded, this is my JS file:
//* AJAX *//
startAsyncNews: function(){
if(this.sendimage){
var formdata = new FormData();
formdata.append("file",this.contentnew.imageFile );
console.log(this.contentnew.imageFile);
}
// POST /someUrl
this.$http.post('controllers/newsController.php', {
data:{action : this.accion_new, data_new: this.contentnew , imgf : formdata}
}).then(response => {
}, response => {
console.log("error");
});
},
imageSelect: function($event){
this.sendimage=true;
this.contentnew.imageFile =$event.target.files[0];
}
When I use the console.log = console.log (this.contentnew.imageFile), it shows me the properties of the image correctly, that is, it is sending the file well, but when I receive it in php and I do vardump I get this object ( stdclass) # 3 (0) no properties no properties and with json_decode / encode I get it empty, also try
headers: {
'content-type': 'multipart/form-data'
}
But it generates the following error:
Missing boundary in multipart/form-data POST
You need to add all your data in formdata Object using formdata.append(key,value) function.
Then you simply send formdata
formdata.append('action ',this.accion_new);
formdata.append('data_new',this.contentnew);
this.$http.post('controllers/newsController.php', {
data:formdata
});
// or just if i'm not mistaken
this.$http.post('controllers/newsController.php',formdata);
object in http request data.
I don't know what this.accion_new and this.contentnew are, but this line:
this.$http.post('controllers/newsController.php', {
data:{action : this.accion_new, data_new: this.contentnew , imgf : formdata}
})
should simply be be:
this.$http.post('controllers/newsController.php', formdata)

How to POST an XML with Angular http?

I'm having trouble using JavaScript to send xml. I've tried to emulate what many others have done, but I'm not getting success. I'm getting a XML Syntax Error: Please check the XML request to see if it can be parsed. with the code 80040B19.
Here's my code. I'm trying to use the USPS Address Validation API. On page 4 of this doc, there's more info.
const apiUrl = 'http://production.shippingapis.com/ShippingAPI.dll?API=Verify';
validate(address: Object): any {
const payload = this.xmlBuilder.buildObject({
AddressValidateRequest: {
$: { USERID: 'XXXXXXXXX' }, // api key hidden
Address: {
$: { ID: '0'},
FirmName: null,
Address1: address['address2'],
Address2: address['address1'], // NOT A TYPO, they swap it
City: address['city'],
State: 'NY',
Zip5: address['postal_code'],
Zip4: null
}
}
});
console.log(payload); // SEE BELOW
const headers = new Headers({ 'Content-Type': 'text/xml' });
const options = new RequestOptions({ headers: headers });
return this.http.post(this.apiUrl, { 'XML': payload }, options)
.map((res) => {
this.parseXMLStringToObject(res.text(), (err, result) => {
console.log(result);
});
});
}
Here's what my console.log on the payload reads. I've verified this to the letter, from the order of the xml tags, to what is required tag but optional value. I'm positive the payload is correct.
<AddressValidateRequest USERID="XXXXXXXXX">
<Address ID="0">
<FirmName/>
<Address1/>
<Address2>620 Eighth Avenue</Address2>
<City>New York</City>
<State>NY</State>
<Zip5>10018</Zip5>
<Zip4/>
</Address>
</AddressValidateRequest>
One thing that I can think of is I'm somehow not using the http correctly, and I'm sending a blank xml somehow.
On their docs, they have this listed:
https://servername/ShippingAPI.dll?API=Verify&XML=……..
I noticed I'm not doing a XML in the url, but I'm assuming that when I input the Content-Type: text/xml, that it get converted. I've also tried application/xml which give the same error.
From the documentation on USPS website it seems that the call isn't a POST with the XML as payload but a GET with XML (I suppose urlencoded) in the URL XML parameter.

Get base64 image from public highchart export server

Is there any way to get a base64 image (instead of png, jpg, pdf) from highcharts public export server?
server: http://export.highcharts.com/
Edit:
what I'm trying to do, is render the charts on server side and store them as base64. I'm able to do that by setting up a small web server following the instructions here highcharts.com/docs/export-module/render-charts-serverside but that means I need to host this in some place, and I'm trying to figure out if that's something I can avoid.
Since this is something I wanted to do from the backend and without the need of rendering the chart first, I ended up getting the image from the public export server and then convert it to base64 from the backend using RestSharp to do the request (C#)
public static string Render(Well well, string type)
{
var client = new RestClient("http://export.highcharts.com");
StringBuilder json = new StringBuilder('the options of the chart');
var request = new RestRequest("/", Method.POST);
request.AddHeader("Content-Type", "multipart/form-data");
request.AddParameter("content", "options");
request.AddParameter("options", json);
request.AddParameter("constr", "Chart");
request.AddParameter("type", "image/png");
var response = (RestResponse) client.Execute(request);
return Convert.ToBase64String(response.RawBytes);
}
I don't see the option base64 in the dropdown. So probably the answer is no.
But you could get the png, jpg or whatever and use something like base64 online to encode it.
Very much late to post But you can get base64 from http://export.highcharts.com.
You need to pass below configuration in Request
let chartData = {
infile: CHART_DATA,
b64: true // Bool, set to true to get base64 back instead of binary.
width: 600,
constr : "Chart"
}
You can use below example
fetch("https://export.highcharts.com/", {
"headers": {
"content-type": "application/json",
},
"body": "{\"infile\":\"{\\n \\\"xAxis\\\": {\\n \\\"categories\\\": [\\n \\\"Jan\\\",\\n \\\"Feb\\\",\\n \\\"Mar\\\",\\n \\\"Apr\\\",\\n \\\"May\\\",\\n \\\"Jun\\\",\\n \\\"Jul\\\",\\n \\\"Aug\\\",\\n \\\"Sep\\\",\\n \\\"Oct\\\",\\n \\\"Nov\\\",\\n \\\"Dec\\\"\\n ]\\n },\\n \\\"series\\\": [\\n {\\n \\\"data\\\": [1,3,2,4],\\n \\\"type\\\": \\\"line\\\"\\n },\\n {\\n \\\"data\\\": [5,3,4,2],\\n \\\"type\\\":\\\"line\\\"\\n }\\n ]\\n}\\n\",\"width\":600,\"constr\":\"Chart\",\"b64\":true}",
"method": "POST",
"mode": "cors"
}).then(function(response) {
// The response is a Response instance.
return response.text();
}).then(function(data) {
console.log(data); // base64 data
}).catch(function(err) { console.log(err);})

Categories

Resources