Closed mehdidarmiche closed 6 years ago
Try to adding crossOrigin
attribute to the image:
<img src="path/to/s3.jpg" crossorigin="anonymous">
Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin
i tried your method ,but it does not work .here is my codes :
<div id="demo" style="display:inline-block;">
测试pc页面生成图片M<br>
<img src="https://ss0.baidu.com/73x1bjeh1BF3odCf/it/u=138126325,1485620701&fm=85&s=7FAB2EC3909A35D01E299C1A030010D2" crossorigin>
</div>
let demo = $("#demo") ;
let $canvas = document.createElement("canvas") ;
let w = demo.width();
let h = demo.height();
let scaleBy = 2;
$canvas.width = w*scaleBy;
$canvas.height = h*scaleBy;
$canvas.style.width = w+"px" ;
$canvas.style.hight = h+"px";
var context = $canvas.getContext("2d");
context.scale(scaleBy,scaleBy);
html2canvas(demo,{
allowTaint: true,
canvas: $canvas,
onrendered:function(canvas){
dataURL = canvas.toDataURL("image/png");
$("body").append(canvas);
},
width:w,
height:h
});
@fengyuanchen my codepen demo address: https://codepen.io/robinson90/pen/LryZEV
doesn't work on mobile devices
@robinson90
you're codepen demo seems to worked well. How did you solve the problem?
The target image server also needs to set the Response Header: Access-Control-Allow-Origin: *
.
I tried every possible solution given on the internet related to this. But In the end I had to fix this by a dirty patch. For those like me who are still struggling to get this done, can try folowing:
Note: My use case was to load an s3 url into my cropper, It might be similar for others as well
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
</CORSRule>
</CORSConfiguration>
<!-- Basically tell your server to allow access-control-allow-origin:* -->
this.cropper = new Cropper(document.getElementById('cropper'), {
checkCrossOrigin:false, // This is important
crop(event) {
setTimeout(()=>{
/**---------------------------------------------------------------------
In order for crossorigin to work we need to add crossorigin attribute
to the dynamically created img element, (See Attachment)
---------------------------------------------------------------------*/
let canvas_img = window.document.querySelector('img.cropper-hide');
let src = canvas_img.getAttribute('src');
canvas_img.setAttribute('crossorigin', 'anonymous')
/*Somehow src needs to be set again in order for crossorigin to work */
canvas_img.setAttribute('src', src)
},100)
}
});
I hope this helps someone.
I tried every possible solution given on the internet related to this. But In the end I had to fix this by a dirty patch. For those like me who are still struggling to get this done, can try folowing:
Note: My use case was to load an s3 url into my cropper, It might be similar for others as well
- Update the URL of s3 to start with http from https
- Added bucket configurations as follow:
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration> <!-- Basically tell your server to allow access-control-allow-origin:* -->
- Initialize cropper
this.cropper = new Cropper(document.getElementById('cropper'), { checkCrossOrigin:false, // This is important crop(event) { setTimeout(()=>{ /**--------------------------------------------------------------------- In order for crossorigin to work we need to add crossorigin attribute to the dynamically created img element, (See Attachment) ---------------------------------------------------------------------*/ let canvas_img = window.document.querySelector('img.cropper-hide'); let src = canvas_img.getAttribute('src'); canvas_img.setAttribute('crossorigin', 'anonymous') /*Somehow src needs to be set again in order for crossorigin to work */ canvas_img.setAttribute('src', src) },100) } });
I hope this helps someone.
you're the best!
@baljeetbhinderI think that cropperjs must check these attributes and added if there exist in the initial image.
- Update the URL of s3 to start with http from https
@baljeetbhinder Is this absolutely necessary ^ - I think it will cause a warning when loading a image in http from a https website (Mixed Content)?
@patricksebastien you made a good point, I just realised that when I wrote my comment above, The task was under development environment which was not having ssl and that is why I had to shift to http to preview it correctly. I did not change the https part in production environment and yet it is working fine there. Thanks for reporting that.
thanks @baljeetbhinder help me to resolve the problem that I add on my project with canvas!
Thanks @baljeetbhinder. You ended my 12 hours struggle.
You may improve it by changing your code be triggered on ready
and not on crop
maybe. Sometimes you don't crop while initialising, like autoCrop: false
. Then crop()
method won't be triggered at all.
Also, you will not need to put setTimeout
if you add the code in ready
as it already takes care of asynchronous thing.
But thanks again 🙂
@schnmudgal Makes sense!! Thank You for updating my knowledge
I tried every possible solution given on the internet related to this. But In the end I had to fix this by a dirty patch. For those like me who are still struggling to get this done, can try folowing:
Note: My use case was to load an s3 url into my cropper, It might be similar for others as well
- Update the URL of s3 to start with http from https
- Added bucket configurations as follow:
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration> <!-- Basically tell your server to allow access-control-allow-origin:* -->
- Initialize cropper
this.cropper = new Cropper(document.getElementById('cropper'), { checkCrossOrigin:false, // This is important crop(event) { setTimeout(()=>{ /**--------------------------------------------------------------------- In order for crossorigin to work we need to add crossorigin attribute to the dynamically created img element, (See Attachment) ---------------------------------------------------------------------*/ let canvas_img = window.document.querySelector('img.cropper-hide'); let src = canvas_img.getAttribute('src'); canvas_img.setAttribute('crossorigin', 'anonymous') /*Somehow src needs to be set again in order for crossorigin to work */ canvas_img.setAttribute('src', src) },100) } });
I hope this helps someone.
If you do have to support IE11 note that this newer ES6 method definition
crop(event) {
is not supported.
Instead use the old fashioned
crop: function(event) {
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions
I tried every possible solution given on the internet related to this. But In the end I had to fix this by a dirty patch. For those like me who are still struggling to get this done, can try folowing:
Note: My use case was to load an s3 url into my cropper, It might be similar for others as well
- Update the URL of s3 to start with http from https
- Added bucket configurations as follow:
<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration> <!-- Basically tell your server to allow access-control-allow-origin:* -->
- Initialize cropper
this.cropper = new Cropper(document.getElementById('cropper'), { checkCrossOrigin:false, // This is important crop(event) { setTimeout(()=>{ /**--------------------------------------------------------------------- In order for crossorigin to work we need to add crossorigin attribute to the dynamically created img element, (See Attachment) ---------------------------------------------------------------------*/ let canvas_img = window.document.querySelector('img.cropper-hide'); let src = canvas_img.getAttribute('src'); canvas_img.setAttribute('crossorigin', 'anonymous') /*Somehow src needs to be set again in order for crossorigin to work */ canvas_img.setAttribute('src', src) },100) } });
I hope this helps someone.
I tried it as what commented by you, but got another exception.
InvalidStateError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The HTMLImageElement provided is in the 'broken' state.
getSourceCanvas
node_modules/cropperjs/dist/cropper.js:1013
1010 | context.scale(scaleX, scaleY); 1011 | context.imageSmoothingEnabled = imageSmoothingEnabled; 1012 | context.imageSmoothingQuality = imageSmoothingQuality; 1013 | context.drawImage.apply(context, [image].concat(_toConsumableArray(params.map(function (param) { 1014 | return Math.floor(normalizeDecimalNumber(param)); 1015 | })))); 1016 | context.restore();
Hey. Is there a React equivalent to this fix?
@baljeetbhinder I have a similar issue in my react canvas app. I am using images from http://traits.s3.filebase.com/...png on my React-Canvas. But it won't allow me to save them.
function saveImage() {
let imageToSave = new Image();
imageToSave.crossOrigin="anonymous"
imageToSave.src = hiddenCanvas.current.toDataURL('image/png', 1.0);
setSavedImage(imageToSave.src)
}
Trying to display <img src={savedImage} alt="test result" crossOrigin></img>
I added that crossOrigin line. But no success. What else is needed?
@baljeetbhinder I also added the following CORS json to the server hosting my images:
{
"CORSRules": [
{
"AllowedHeaders": [],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]
}
@baljeetbhinder adding CORS and the anon tags in react hasnt worked for me still! Someone plz answer my SO query here: https://t.co/jBXmxvn3Ao
Try to adding
crossOrigin
attribute to the image:<img src="path/to/s3.jpg" crossorigin>
- <img src="path/to/s3.jpg" crossorigin>
+ <img src="path/to/s3.jpg" crossorigin="anonymous">
situation: using js auto download image with canvas API
function autoDownloadImageWithCanvas(src = "https://cdn.xgqfrms.xyz/logo/icon.png") {
const canvas = document.createElement("canvas");
canvas.width = 300;
canvas.height = 300;
const ctx = canvas.getContext("2d");
const img = document.createElement(`img`);
// fix: Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
// img.crossorigin = "anonymous"; // ❌
img.setAttribute('crossorigin', 'anonymous'); // ✅
img.src = src;
img.onload = function() {
ctx.drawImage(img, 0, 0);
setTimeout(() => {
const dataURL = canvas.toDataURL();
console.log(`dataURL =`, dataURL);
const a = document.createElement(`a`);
a.href = dataURL;
a.download = src.slice(src.lastIndexOf(`/`) + 1);
a.click();
}, 0);
}
}
autoDownloadImageWithCanvas();
https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image#security_and_tainted_canvases
@xgqfrms crossorigin
= crossorigin=""
= crossorigin="anonymous"
.
Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin
@fengyuanchen
You're right, but I think it's best to make explicit statements to avoid unnecessary misunderstandings.
And, crossorigin
isn't a boolean attribute of the HTML5 specification.
https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes
@xgqfrms All right, I will update the original/first answer.
Have you guys found any relevant react solution for this? I have added the cross-origin thing but still facing the same error. @developdeez
I'm trying to crop an image from a link, it works for the first time but when i reload the page and i try to crop the same image i got ( Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. ) i use amazon s3 for storage and i configure* as CORS Rule .
Thanks a lot.