问题
I'm trying to figure out how to upload an image using ngx-awesome-uploader to azure storage blob from Angular.
I'd like to be able to send it directly to azure storage blob from angular using this library. I've been able to send it to my nodejs backend no problem, but it's been challenging for me to send it directly to blob storage instead. Can anyone provide a working example of how to do this? I appreciate any help!
Choose Simple Demo in stackblitz. Not Advanced Demo
Stackblitz example of ngx awesome uploader
The file is passed to this. (Console output below code)
import { FilePreviewModel } from 'ngx-awesome-uploader';
import { HttpRequest, HttpClient, HttpEvent, HttpEventType } from '@angular/common/http';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
import { FilePickerAdapter } from 'ngx-awesome-uploader';
export class DemoFilePickerAdapter extends FilePickerAdapter {
constructor(private http: HttpClient) {
super();
}
public uploadFile(fileItem: FilePreviewModel) {
const form = new FormData();
form.append('file', fileItem.file);
console.log("FILE OUTPUT");
console.log(fileItem.file);
//need to replace everything below with code to add to storage blob
const api = 'https://demo-file-uploader.free.beeceptor.com';
const req = new HttpRequest('POST', api, form, {reportProgress: true});
return this.http.request(req)
.pipe(
map( (res: HttpEvent<any>) => {
if (res.type === HttpEventType.Response) {
return res.body.id.toString();
} else if (res.type === HttpEventType.UploadProgress) {
// Compute and show the % done:
const UploadProgress = +Math.round((100 * res.loaded) / res.total);
return UploadProgress;
}
})
);
}
}
the console.output of FILE OUTPUT is
回答1:
According to my test, if you want to upload file to Azure blob, please refer to the following steps
- install Azure storage SDk
npm install @azure/storage-blob
- Update app.component.html File
<div class="form-group">
<label for="file">Choose File</label>
<input type="file"
id="file"
(change)="onFileChange($event)">
</div>
- Update Environment.ts
export const environment = {
production: false,
accountName : "<account name>",
containerName:"",
key:""
};
- Add the following code in polyfills.ts
(window as any).global = window;
(window as any).process = require( 'process' );
(window as any).Buffer = require( 'buffer' ).Buffer;
- Add the following code in app.component.ts
import { Component } from '@angular/core';
import {BlobServiceClient,AnonymousCredential,newPipeline } from '@azure/storage-blob';
import { environment } from './../environments/environment';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'web1';
currentFile : File =null;
onFileChange(event) {
this.currentFile = event.target.files[0];
console.log(this.currentFile.name)
console.log(this.currentFile.type)
// generate account sas token
const accountName =environment.accountName;
const key=environment.key;
const start = new Date(new Date().getTime() - (15 * 60 * 1000));
const end = new Date(new Date().getTime() + (30 * 60 * 1000));
const signedpermissions = 'rwdlac';
const signedservice = 'b';
const signedresourcetype = 'sco';
const signedexpiry = end.toISOString().substring(0, end.toISOString().lastIndexOf('.')) + 'Z';
const signedProtocol = 'https';
const signedversion = '2018-03-28';
const StringToSign =
accountName+ '\n' +
signedpermissions + '\n' +
signedservice + '\n' +
signedresourcetype + '\n' +
'\n' +
signedexpiry + '\n' +
'\n' +
signedProtocol + '\n' +
signedversion + '\n';
const crypto =require('crypto')
const sig = crypto.createHmac('sha256', Buffer.from(key, 'base64')).update(StringToSign, 'utf8').digest('base64');
const sasToken =`sv=${(signedversion)}&ss=${(signedservice)}&srt=${(signedresourcetype)}&sp=${(signedpermissions)}&se=${encodeURIComponent(signedexpiry)}&spr=${(signedProtocol)}&sig=${encodeURIComponent(sig)}`;
const containerName=environment.containerName;
const pipeline =newPipeline (new AnonymousCredential(),{
retryOptions: { maxTries: 4 }, // Retry options
userAgentOptions: { userAgentPrefix: "AdvancedSample V1.0.0" }, // Customized telemetry string
keepAliveOptions: {
// Keep alive is enabled by default, disable keep alive by setting false
enable: false
}
});
const blobServiceClient =new BlobServiceClient(`https://${accountname}.blob.core.windows.net?${sasToken}`,
pipeline )
const containerClient =blobServiceClient.getContainerClient(containerName)
if(!containerClient.exists()){
console.log("the container does not exit")
await containerClient.create()
}
const client = containerClient.getBlockBlobClient(this.currentFile.name)
const response = await client.uploadBrowserData(this.currentFile,{
blockSize: 4 * 1024 * 1024, // 4MB block size
concurrency: 20, // 20 concurrency
onProgress: (ev) => console.log(ev),
blobHTTPHeaders :{blobContentType:this.currentFile.type}
})
console.log(response._response.status)
}
}
- Configure CORS for Azure storage
Allowed origins: *
Allowed verbs: DELETE,GET,HEAD,MERGE,POST,OPTIONS,PUT
Allowed headers: *
Exposed headers: *
Maximum age (seconds): 86400
- Test. I upload a pdf file
Regarding how to configure CORS, please refer to the following steps
Sign in Azure Portal.
Select the Azure account you use
Configure CORS
Update
If you cannot use function createHmac
, you can try to use crypto-js
. The detailed steps are as below
- install sdk
npm install crypto-js --save
npm install @types/crypto-js --save-dev
- Update code in the in app.component.ts
...
import * as CryptoJS from 'crypto-js';
...
export class AppComponent {
title = 'web1';
currentFile : File =null;
onFileChange(event) {
this.currentFile = event.target.files[0];
console.log(this.currentFile.name)
console.log(this.currentFile.type)
// generate account sas token
const accountName =environment.accountName;
const key=environment.key;
const start = new Date(new Date().getTime() - (15 * 60 * 1000));
const end = new Date(new Date().getTime() + (30 * 60 * 1000));
const signedpermissions = 'rwdlac';
const signedservice = 'b';
const signedresourcetype = 'sco';
const signedexpiry = end.toISOString().substring(0, end.toISOString().lastIndexOf('.')) + 'Z';
const signedProtocol = 'https';
const signedversion = '2018-03-28';
const StringToSign =
accountName+ '\n' +
signedpermissions + '\n' +
signedservice + '\n' +
signedresourcetype + '\n' +
'\n' +
signedexpiry + '\n' +
'\n' +
signedProtocol + '\n' +
signedversion + '\n';
var str =CryptoJS.HmacSHA256(StringToSign,CryptoJS.enc.Base64.parse(key));
var sig = CryptoJS.enc.Base64.stringify(str);
const sasToken =`sv=${(signedversion)}&ss=${(signedservice)}&srt=${(signedresourcetype)}&sp=${(signedpermissions)}&se=${encodeURIComponent(signedexpiry)}&spr=${(signedProtocol)}&sig=${encodeURIComponent(sig)}`;
const containerName=environment.containerName;
const pipeline =newPipeline (new AnonymousCredential(),{
retryOptions: { maxTries: 4 }, // Retry options
userAgentOptions: { userAgentPrefix: "AdvancedSample V1.0.0" }, // Customized telemetry string
keepAliveOptions: {
// Keep alive is enabled by default, disable keep alive by setting false
enable: false
}
});
const blobServiceClient =new BlobServiceClient(`https://${accountname}.blob.core.windows.net?${sasToken}`,
pipeline )
const containerClient =blobServiceClient.getContainerClient(containerName)
if(!containerClient.exists()){
console.log("the container does not exit")
await containerClient.create()
}
const client = containerClient.getBlockBlobClient(this.currentFile.name)
const response = await client.uploadBrowserData(this.currentFile,{
blockSize: 4 * 1024 * 1024, // 4MB block size
concurrency: 20, // 20 concurrency
onProgress: (ev) => console.log(ev),
blobHTTPHeaders :{blobContentType:this.currentFile.type}
})
console.log(response._response.status)
}
}
来源:https://stackoverflow.com/questions/60533341/adding-file-to-azure-storage-blob-from-angular