Angular:Cloudinary 错误 “消息”:“cloud_name 已禁用”
Posted
技术标签:
【中文标题】Angular:Cloudinary 错误 “消息”:“cloud_name 已禁用”【英文标题】:Angular: Cloudinary error "message": "cloud_name is disabled" Angular:Cloudinary 错误 “消息”:“cloud_name 已禁用” 【发布时间】:2020-12-21 03:35:09 【问题描述】:我正在尝试通过 Angular 使用 Cloudinary 图像上传。 我已经按照他们的文档安装了图片上传器 sdk。我已经关注了组件和 html 的一些示例项目。
在我的项目中一切正常,但是当我尝试上传图片时,我不断收到错误消息:
Upload completed with status code 401
error "message": "cloud_name is disabled"
这是我的component.ts
:
import Component, OnInit, Input, NgZone from '@angular/core';
import HttpClient from '@angular/common/http';
import FileUploader, FileUploaderOptions, ParsedResponseHeaders, FileUploadModule from 'ng2-file-upload';
import Cloudinary from '@cloudinary/angular-5.x';
// https://www.youtube.com/watch?v=YkvqLNcJz3Y
@Component(
selector: 'app-cloudinary',
templateUrl: './cloudinary.component.html',
styleUrls: ['./cloudinary.component.scss']
)
export class CloudinaryComponent implements OnInit
@Input()
responses: Array<any>;
public hasBaseDropZoneOver: boolean = false;
public uploader: FileUploader;
private title: string;
constructor(
private cloudinary: Cloudinary,
private zone: NgZone,
private http: HttpClient
)
this.responses = [];
this.title = '';
ngOnInit(): void
// Create the file uploader, wire it to upload to your account
const uploaderOptions: FileUploaderOptions =
url: `https://api.cloudinary.com/v1_1/$this.cloudinary.config().CLOUD_NAME/upload`,
// Upload files automatically upon addition to upload queue
autoUpload: true,
// Use xhrTransport in favor of iframeTransport
isHTML5: true,
// Calculate progress independently for each uploaded file
removeAfterUpload: true,
// XHR request headers
headers: [
name: 'X-Requested-With',
value: 'XMLHttpRequest'
]
;
this.uploader = new FileUploader(uploaderOptions);
this.uploader.onBuildItemForm = (fileItem: any, form: FormData): any =>
// Add Cloudinary's unsigned upload preset to the upload form
form.append('upload_preset', this.cloudinary.config().upload_preset);
// Add built-in and custom tags for displaying the uploaded photo in the list
let tags = 'myphotoalbum';
if (this.title)
form.append('context', `photo=$this.title`);
tags = `myphotoalbum,$this.title`;
// Upload to a custom folder
// Note that by default, when uploading via the API, folders are not automatically created in your Media Library.
// In order to automatically create the folders based on the API requests,
// please go to your account upload settings and set the 'Auto-create folders' option to enabled.
form.append('folder', 'angular_sample');
// Add custom tags
form.append('tags', tags);
// Add file to upload
form.append('file', fileItem);
// Use default "withCredentials" value for CORS requests
fileItem.withCredentials = false;
return fileItem, form ;
;
// Insert or update an entry in the responses array
const upsertResponse = fileItem =>
// Run the update in a custom zone since for some reason change detection isn't performed
// as part of the XHR request to upload the files.
// Running in a custom zone forces change detection
this.zone.run(() =>
// Update an existing entry if it's upload hasn't completed yet
// Find the id of an existing item
const existingId = this.responses.reduce((prev, current, index) =>
if (current.file.name === fileItem.file.name && !current.status)
return index;
return prev;
, -1);
if (existingId > -1)
// Update existing item with new data
this.responses[existingId] = Object.assign(this.responses[existingId], fileItem);
else
// Create new response
this.responses.push(fileItem);
);
;
// Update model on completion of uploading a file
this.uploader.onCompleteItem = (item: any, response: string, status: number, headers: ParsedResponseHeaders) =>
upsertResponse(
file: item.file,
status,
data: JSON.parse(response)
);
// Update model on upload progress event
this.uploader.onProgressItem = (fileItem: any, progress: any) =>
upsertResponse(
file: fileItem.file,
progress,
data:
);
updateTitle(value: string)
this.title = value;
// Delete an uploaded image
// Requires setting "Return delete token" to "Yes" in your upload preset configuration
// See also https://support.cloudinary.com/hc/en-us/articles/202521132-How-to-delete-an-image-from-the-client-side-
deleteImage = function (data: any, index: number)
const url = `https://api.cloudinary.com/v1_1/$this.cloudinary.config().CLOUD_NAME/delete_by_token`;
const headers = new Headers( 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' );
const options = headers: headers ;
const body =
token: data.delete_token
;
this.http.post(url, body, options).subscribe(response =>
console.log(`Deleted image - $data.public_id $response.result`);
// Remove deleted item for responses
this.responses.splice(index, 1);
);
;
fileOverBase(e: any): void
this.hasBaseDropZoneOver = e;
getFileProperties(fileProperties: any)
// Transforms javascript Object to an iterable to be used by *ngFor
if (!fileProperties)
return null;
return Object.keys(fileProperties)
.map((key) => ( 'key': key, 'value': fileProperties[key] ));
这是我的component.html
:
<h1>Image Upload to Cloudinary TESTING</h1>
<div id="direct_upload" ng2FileDrop [uploader]="uploader" (fileOver)="fileOverBase($event)" [ngClass]="'nv-file-over': hasBaseDropZoneOver">
<h1>New Photo</h1>
<h2>Direct upload from the browser with Angular File Upload</h2>
<p>You can also drag and drop an image file into the dashed area.</p>
<form>
<div class="form_line">
<label path="title">Title:</label>
<div class="form_controls">
<input type="text" class="form-control" #title placeholder="Title" (keyup.enter)="updateTitle(title.value)" (blur)="updateTitle(title.value)"
/>
</div>
</div>
<div class="form_line">
<label>Image:</label>
<div class="form_controls">
<div class="upload_button_holder">
<label class="upload_button" for="fileupload">Upload</label>
<!-- onChange hanlder resets the input value to get the change event when uploading the same file consecutively -->
<input type="file" id="fileupload" #fileInput ng2FileSelect [style.display]="'none'" [uploader]="uploader" (change)="fileInput.value=''"
multiple />
</div>
</div>
</div>
</form>
<h2>Status</h2>
<div class="file" *ngFor="let response of responses; let i = index">
<h3>response.file.name</h3>
<button class="delete-image" *ngIf="!!response.data.delete_token" (click)="deleteImage(response.data, i)">Delete image</button>
<div class="status">
Uploading... response.progress%
<div *ngIf="!response.status">In progress</div>
<div class="status-code" *ngIf="response.status">Upload completed with status code response.status</div>
</div>
<div class="progress-bar">
<div class="progress" role="progressbar" [style.width.%]="response.progress"></div>
</div>
<div class="form_line">
<div class="form_controls">
<div class="preview">
<!-- Consider using https://github.com/valor-software/ng2-file-upload/issues/461 for image preview -->
</div>
</div>
</div>
<div class="info">
<table>
<tr *ngFor="let property of getFileProperties(response.data)">
<td> property.key </td>
<td> property.value | json </td>
</tr>
</table>
</div>
</div>
</div>
在我的app.module.ts
中我做了我的导入:
...
import CloudinaryModule, CloudinaryConfiguration from '@cloudinary/angular-5.x';
import Cloudinary from 'cloudinary-core';
import FileUploadModule from "ng2-file-upload";
@NgModule(
declarations: [
...
CloudinaryComponent
],
imports: [
...
// Cloudinary import
CloudinaryModule.forRoot(Cloudinary, cloud_name: 'CLOUDN_NAME' as CloudinaryConfiguration),
FileUploadModule
],
providers: [
...
],
bootstrap: [AppComponent]
)
export class AppModule
所以我真的不明白为什么它没有获得授权,但也让我感到困扰的是,在带有 Angular 的 Cloudinary 文档中,我看不到应该将我的 API Key
和 API Secret
放在哪里。
在我的项目中,我没有像 systemjs.config.js
rollup-config.js
这样的文件。
如果有人可以帮助我,那就太棒了!
谢谢
【问题讨论】:
您好,好像是URL中的云名配置错误。尝试仅包含“CLOUD_NAME”(而不是 $this.cloudinary.config().CLOUD_NAME)。 【参考方案1】:在您的示例中,您需要更改云 URL
。
你有https://api.cloudinary.com/v1_1/$this.cloudinary.config().CLOUD_NAME/upload
,但你需要https://api.cloudinary.com/v1_1/CLOUD_NAME/upload
。
你的https://api.cloudinary.com/v1_1/$this.cloudinary.config().CLOUD_NAME/delete_by_token
也需要改成https://api.cloudinary.com/v1_1/CLOUD_NAME/delete_by_token
您的upload_preset
需要将其从form.append('upload_preset', this.cloudinary.config().upload_preset)
更改为form.append('upload_preset', 'PRESET_NAME')
所以你的组件应该是这样的:
...
ngOnInit(): void
// Create the file uploader, wire it to upload to your account
const uploaderOptions: FileUploaderOptions =
url: `https://api.cloudinary.com/v1_1/$this.cloudinary.config().CLOUD_NAME/upload`,
// Upload files automatically upon addition to upload queue
autoUpload: true,
// Use xhrTransport in favor of iframeTransport
isHTML5: true,
// Calculate progress independently for each uploaded file
removeAfterUpload: true,
// XHR request headers
headers: [
name: 'X-Requested-With',
value: 'XMLHttpRequest'
]
;
this.uploader = new FileUploader(uploaderOptions);
this.uploader.onBuildItemForm = (fileItem: any, form: FormData): any =>
// Add Cloudinary's unsigned upload preset to the upload form
form.append('upload_preset', 'PRESET_NAME');
// Add built-in and custom tags for displaying the uploaded photo in the list
let tags = 'myphotoalbum';
if (this.title)
form.append('context', `photo=$this.title`);
tags = `myphotoalbum,$this.title`;
// Upload to a custom folder
// Note that by default, when uploading via the API, folders are not automatically created in your Media Library.
// In order to automatically create the folders based on the API requests,
// please go to your account upload settings and set the 'Auto-create folders' option to enabled.
form.append('folder', 'angular_sample');
// Add custom tags
form.append('tags', tags);
// Add file to upload
form.append('file', fileItem);
// Use default "withCredentials" value for CORS requests
fileItem.withCredentials = false;
return fileItem, form ;
;
...
// Delete an uploaded image
// Requires setting "Return delete token" to "Yes" in your upload preset configuration
// See also https://support.cloudinary.com/hc/en-us/articles/202521132-How-to-delete-an-image-from-the-client-side-
deleteImage = function (data: any, index: number)
const url = `https://api.cloudinary.com/v1_1/CLOUD_NAME/delete_by_token`;
const headers = new Headers( 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' );
const options = headers: headers ;
const body =
token: data.delete_token
;
...
对于API key
,如果您要上传到签名的upload_preset
,您可以像这样在组件中输入密钥,如sample project angular 所示:
...
ngOnInit(): void
console.log("initialized");
(window as any).cloudinary.createMediaLibrary(
cloud_name: "<cloud name>",
api_key: "<api key>",
button_class: "myBtn",
username: "<user email>",
button_caption: "Select Image or Video"
,
...
【讨论】:
感谢您的回答!但是,我应该在某处提供 API 密钥和秘密吗?以上是关于Angular:Cloudinary 错误 “消息”:“cloud_name 已禁用”的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 中动态嵌入来自 Cloudinary 的第三方 javascript 小部件?
Angular cloudinary 自动播放具有响应宽度/高度的视频