Изначально у меня было приложение Angular 8+ с формой загрузки и некоторым кодом, который генерировал предварительно назначенные URL-адреса AWS, которые использовались для загрузки файла, выбранного в форме загрузки, в контейнеры AWS S3. Код выглядел примерно так:
const AWS = require('aws-sdk');
import { Component, OnInit, } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../../environments/environment';
@Component({
selector: 'app-upload-page',
templateUrl: './upload-page.component.html',
styleUrls: ['./upload-page.component.scss']
})
export class UploadComponent implements OnInit {
private S3: any;
private UPLOAD_FOLDER = 'test/';
public file: File;
constructor(private http: HttpClient) {}
ngOnInit(): void {
AWS.config.update({
accessKeyId: environment.amazon.s3.secretAccessId,
secretAccessKey: environment.amazon.s3.secretAccessKey,
region: environment.amazon.s3.region,
signatureVersion: environment.amazon.s3.signatureVersion
});
this.S3 = new AWS.S3();
}
// Triggered when clicking the upload button after attaching a file to <input type="file"/>
public async onUpload(): Promise<void> {
try {
const params = this.buildUploadParams(environment.amazon.s3.bucketname, this.UPLOAD_FOLDER + this.file.name, this.file.type, 120);
const preSignedGetUrl = this.S3.getSignedUrl('putObject', params);
await this.upload(preSignedGetUrl, this.file); // this.file is the body
this.file = null;
} catch (error) {
console.error(error);
}
}
// Triggered when selecting a file
public onChange($event: any): void {
const files = $event.srcElement.files;
this.file = files[0];
}
// Triggers the presigned url and attaches this.file to body
private upload(url: string, body: any): Promise<any> {
return new Promise((resolve, reject) => {
this.http.put(url, body).toPromise()
.then(res => resolve(res), (error: any) => reject(error));
});
}
// Builds params required to generate presigned urls
private buildUploadParams(bucket: string, key: string, contentType: string, expires: number): any {
return {
Bucket: bucket,
Key: key,
ContentType: contentType,
ACL: 'bucket-owner-full-control',
Expires: expires
};
}
}
Этот код работает нормально, но я хочу снять ответственность за генерацию предопределенных URL-адресов из клиента (Angular 8+) для функций AWS Lambda в приложении Node.js.
Итак, я добавляю новую среду. Экземпляр Node.js, который я развертываю через Netlify, чтобы я мог легко получить доступ к функциям AWS Lambda через URL-адреса, например, https://my -url.netlify.com / .netlify / functions / upload? File = '+файл.
Вот так выглядит моя лямбда-функция AWS в файле functions / upload.js в экземпляре Node.js:
// Below is the content of the upload.js file
const AWS = require('aws-sdk');
const request = require('request');
// AWS credentials
const S3_ACCESS_KEY_ID = 'MY_ACCESS_KEY_ID';
const S3_SECRET_ACCESS_KEY = 'MY_SECRET_ACCESS_KEY';
const BUCKET_NAME = 'MY_BUCKET_NAME';
const UPLOAD_FOLDER = 'test/';
AWS.config.update({
accessKeyId: S3_ACCESS_KEY_ID,
secretAccessKey: S3_ACCESS_ACCESS_KEY,
region: 'eu-west-1',
signatureVersion: 'v4'
});
const s3 = new AWS.S3();
function buildUploadParams(bucket, key, contentType, expires) {
return {
Bucket: bucket,
Key: key,
ContentType: contentType,
ACL: 'bucket-owner-full-control',
Expires: expires
}
}
function upload(url, body) {
return new Promise((resolve, reject) => {
request({ method: 'PUT', url: url, body: body }, (error, response, body) => {
if (error) {
return reject(error);
}
if (response.statusCode !== 200) {
return reject(body.error_description);
}
resolve();
});
});
}
function response (code, body) {
return {
'statusCode': code,
'headers': { 'Access-Control-Allow-Origin': '*' },
'body': body,
'isBase64Encoded': false
}
}
async function uploadFile(file) {
const params = buildUploadParams(BUCKET_NAME, UPLOAD_FOLDER, file.type, 120);
const preSignedGetUrl = s3.getSignedUrl('putObject', params);
await upload(preSignedGetUrl, file);
return 'Successfully uploaded file';
}
// AWS Lambda Function
exports.handler = async (event, context, callback) => {
// Should I pass file content with the query and get it like this: event.queryStringParameters['file'];
const file = event.queryStringParameters['file'];
callback(null, response(200, uploadFile(file)));
};
Затем я могу сделать HTTP-запрос POST к Netlify. URL-адрес, по которому я передаю файл в качестве параметра от клиента Angular 8+ в URL-адресе Netlify, но вы не можете передать файловый объект [File object] в качестве параметра URL-адреса, поэтому как мне продолжить?
Вопросы, которые могут помочь мне понять, как перенести this.file из Angular в Node.js. Функции AWS Lambda:
Вместо добавления всего объекта this.file при использовании предварительно назначенного URL-адреса,я могу просто использовать содержимое файла? Если да, в каких формах?
Каково ваше мнение об этом подходе в целом?
Существуют ли альтернативные подходы (Требование: я все ещенужно использовать Angular, Node.js и Netlify)