问题
不要忽略错误消息。 CORS 问题与服务器未提供正确的标头以允许从您的网站 javascript 代码进行跨源访问有关!正如错误所说
请求的资源上不存在“Access-Control-Allow-Origin”标头。
问题不在于您的客户端。 Angular 不会产生这个错误。出于安全原因,您的浏览器正在阻止该请求。服务器刚刚决定不允许此类请求。您可以直接从浏览器访问资源这一事实可能会欺骗您,但在这种情况下,您以不同的方式访问资源(即不是从 javascript XMLHttpRequest)。
如果您想完全理解 CORS,请阅读它:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
解决方案
使用 HttpClient 下载 javascript 文件不会使您能够使用小部件!您必须将 cloudinary js 文件嵌入到您的 html 中才能使用它。
动态嵌入和创建 javascript 小部件的服务可能如下所示:
import { Injectable, RendererFactory2, Renderer2 } from '@angular/core';
import { Observable, of, fromEvent } from 'rxjs';
import { map } from 'rxjs/operators';
declare let cloudinary: any; // declare js widget variable
const widgetUrl = 'https://widget.cloudinary.com/v2.0/global/all.js';
@Injectable({
providedIn: 'root'
})
export class CloudinaryService {
private renderer: Renderer2;
constructor(rendererFactory: RendererFactory2) {
this.renderer = rendererFactory.createRenderer(null, null);
}
// create the upload widget
createUploadWidget(data: any, callback: (error: any, result: any) => void): Observable<any> {
return this.skriptExists(widgetUrl)
// js is embeded -> call js function directly
? of(cloudinary.createUploadWidget(data, callback))
// js isn't embeded -> embed js file and wait for it to load
: fromEvent(this.addJsToElement(widgetUrl), 'load').pipe(
// map to call of js function
map(e => cloudinary.createUploadWidget(data, callback))
);
}
// check if js file is already embeded
private skriptExists(jsUrl: string): boolean {
return document.querySelector(`script[src="${jsUrl}"]`) ? true : false;
}
// embed external js file in html
private addJsToElement(jsUrl: string): HTMLScriptElement {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = jsUrl;
this.renderer.appendChild(document.body, script);
return script;
}
}
使用组件中的服务来创建小部件:
export class AppComponent implements OnInit {
widget: any;
constructor(private cloudinary: CloudinaryService) { }
ngOnInit() {
this.cloudinary.createUploadWidget(
{
cloudName: 'my_cloud_name',
uploadPreset: 'my_preset'
},
(error, result) => {
if (!error && result && result.event === "success") {
console.log('Done! Here is the image info: ', result.info);
}
}
).subscribe(widget => this.widget = widget);
}
openWidget() {
if (this.widget) {
console.log('open')
this.widget.open();
}
}
}