Getting a black image generated from a blob URL - javascript

I am using a library react-avatar-editor for creating profile picture of the user. Below is the code which I am using the send the cropped image to the server
const canvasScaled = this.editor.getImageScaledToCanvas(); //a canvas object
canvasScaled.toBlob((blob) => {
this.setState({
preview: blob
},
() => {
let data = new FormData();
const file = new File([blob], "my-image", {
type: "image/png"
});
data.append("file", file);
axios({
method: "POST",
data: data,
url: "/media",
headers: {
'Content-Type': 'multipart/form-data'
}
}).then().catch()
}
);
})
But the image generated at the server is a black image. Tested with many files but result is same - a black image.
My backend service is written in JAVA so I tested if the backend service handling the image correctly or not, I wrote a simple file selected
<input type="file" accept={"image/png"} onChange={onSelect}/>
<button onClick={() => {
const data = new FormData();
data.append("file", this.state.file);
axios({
method: "POST",
data: data,
url: "/media",
headers: {
'Content-Type': 'multipart/form-data'
}
}).then().catch()
}}>Send<button>
And yes, the service side code is working fine with above POST request. Which means, I have definitely something wrong written at the react-avatar-editor handling code.
Is it the blob causing the issue? How the image is sent in the case of a file-selector? Base64 or blob?
Update: I noticed a strange behavior with an image. If I upload this file
This gets converted to
which is not a complete black image. Something fishy is going on with colors.
To check if the library itself is creating the black image, I check it using canvasScaled.toDataURL("image/png") and used this into an image, and yes there is no issue with the created canvas, image is getting rendered.

Try data.append("file", blob); without calling new File. According to MDN,
A File object is a specific kind of a Blob, and can be used in any context that a Blob can. In particular, FileReader, URL.createObjectURL(), createImageBitmap(), and XMLHttpRequest.send() accept both Blobs and Files.

add this in second line after defining canvasScaled
var ctx = canvasScaled.getContext("2d");
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);

Related

PDF Blob is showing nothing in new tab, using stream from backend

I used https://github.com/barryvdh/laravel-dompdf
stream method for sending a response to front-end.
Here is my code which I wrote for opening pdf in a new tab.I'm calling stream from backend API in result it gives a response but when I try to create blob it shows nothing in PDF.
APICaller({
method: 'get',
responseType: "arraybuffer",
headers: {
'Accept': 'application/pdf'
},
endpoint: gep('generate/certificate?path=certificate.pdf', 'v3'),
}).then( (data) => {
var file = new Blob([data.data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
});
here is Empty PDF
I had a similar issue with axios, it doesn't work for downloading files using Blob. Use XMLHttpRequest and do the similar response handler in its on('load') event to achieve file download.

Generating PDF from wkhtml using PHP wrapper, when sent back to Angular 4, opens only in Chrome

I generate a html in Angular 4, send it to PHP wrapper for wkhtmltopdf, after that it is returned to Angular, and this works fine in Chrome, the PDF is displayed. I need it to be displayed also in Firefox. This is the code that sends the PDF to PHP:
public getPdf() {
const html = this.pdfEl.innerHTML;
alert(html);
this.rest.post(
'/pdf',
{ html },
{
headers: new Headers(),
responseType: ResponseContentType.Blob
}
).subscribe(
(value) => {
//alert('subscribe receiver in pdf button directive');
this.url = URL.createObjectURL(value.blob());
open(this.url);
});
}
Things that I have tried so far, but none worked are:
1. Setting this.url = URL.createObjectURL(new Blob([value.blob()], {type: 'application/pdf'})); instead of this.url = URL.createObjectURL(value.blob());
2. Setting this as headers instead of new Headers() :
new Headers({
'Content-Type': 'application/json',
'Accept': 'application/pdf'
}),
any suggestions to resolve this, guys? Thanks.
If value.blob() returns a Blob you have also set the blob type to application/pdf. That has to be done on the response side, because the property is read only.
Blob Documentation
Blob.type Read only A string indicating the MIME type of the data
contained in the Blob. If the type is unknown, this string is empty.
Or if you value.blob() returns only an array buffer you have to create a new Blob on your own.
new Blob([value.blob()], {type: 'application/pdf'});

JQuery ajax POST with FormData doesn't send any values

There seem to be lots of posts about this, but can't find a solution amongst them and I've hit a brick wall. Help, dear Stackers!
I'm writing a bit of code that lets users choose a profile picture, crop it and then save the cropped image on the server. I'm using the Cropper.js library to handle the actual cropping and have established that's working because I can display the crop live with this code:
var imageData = cropper.getCroppedCanvas().toDataURL();
var profileimage = document.getElementById('myProfilePhoto');
profileimage.src = imageData;
Now I want to send the cropped image to the server, and the best method would appear to be create a blob and Ajax that over to a php script to handle it.
cropper.getCroppedCanvas().toBlob(function (blob) {
var formData = new FormData();
formData.append('file', blob);
formData.append('uuid', '{a unique identifier}');
$.ajax({
type: 'POST',
url: '{the php script}',
data: formData,
processData: false,
contentType: false,
success: function (response) {
console.log('Upload success: '+response);
},
error: function () {
console.log('Upload error');
}
});
});
And at this stage I'm just getting my php script to var_dump($_REQUEST) so I can see in the console what the script thinks it's getting. However, the response is just sending back the default $_REQUEST objects like PHPSESSID and no file or uuid input.
What am I doing wrong?
Thanks in advance for any pointers.
If you are sending via post in order to see the request put this code
var formData = new FormData();
formData.append('file', blob);
formData.append('uuid', '{a unique identifier}');
formData.append('_method', 'PATCH'); <---add this and you're good to go
So the answer was annoyingly simple but frustratingly hard to find.
My server had an .htaccess rewrite rule which automatically changed www. addresses to the non-www version, and obviously I'd been dumb enough to include the www. in the URL I was calling, and it seems that's enough to strip off the $_POST data in these circumstances.
So FormData() and blobs are all red herrings here - it's just a redirect that's the cause.

Pass image as a binary representation

I'm invoking an api that accepts image in the binary representation form. I'm uploading the image through a file upload html.
Here is my code:
let fileReader = new FileReader();
let fileData = fileReader.readAsArrayBuffer(text.data.uploadedFile);
yield call(fetchJson, 'url/fetch', {
method: 'POST',
headers: {
Authentication: 'Basic <key>',
'Content-type': 'image/jpeg'
},
body: fileData
});
I get fileData as undefined and my request does not go through. This 3rd party API accepts image in binary representation form in the body.
This is equivalent to the following in POSTMAN:
This works in POSTMAN but not sure how to achieve this using code.
I set uploadedFile on front-end using: event.target.files[0]

html2canvas javascript screenshot and upload

Would it be possible to use html2canvas (This) to take a picture of the user`s screen but also upload the image, get the upload link and send it with ajax to the webserver?
if so, how can i do this?
Yes it is certainly possible to do such a thing.
Firstly use the html2canvas api to take a picture of the user's screen:
html2canvas(document.body).then(function(canvas) {
});
Secondly use the following function to convert the returned canvas image into a base64 encoded URL (defaults to png):
canvas.toDataURL();
Specification For canvas.toDataURL
Now construct a request to send your base64 encoded url to an image uploading server (I'm using Imgur as an example).
html2canvas(document.body).then(function(canvas) {
var dataURL = canvas.toDataURL();
$.ajax({
url: 'https://api.imgur.com/3/image',
type: 'post',
headers: {
Authorization: 'yourauthcode'
},
data: {
image: dataURL
},
dataType: 'json',
success: function(response) {
if(response.success) {
// Post the imgur url to your server.
$.post("yourlinkuploadserver", response.data.link);
}
}
});
});
After the image has been uploaded you can POST the URL of the uploaded image to your web server.
Specification for $.post
Specification for $.ajax
This isn't tested, but should work
function screenshot() {
html2canvas(document.body).then(function(canvas) {
// post using your favourite xhr polyfill, e.g. jQuery's
$.post('http://urlgoeshere.com', canvas.toDataURL('image/png'));
});
}
Then decode the result from base64 on the server side and put in a file
Using the example above, don't forget to add this to the base64url, otherwise it won't work :
var dataURL = canvas.toDataURL().replace(/.*,/, '');
More info here.

Categories