I've been using a block of code to upload images and documents from my Angular 8 application to my bucket in AWS S3 using "aws-sdk; v2.1237.0", which has been working fairly well without issue for a couple of years now:
import { Injectable } from '@angular/core';
import * as AWS from 'aws-sdk/global';
import * as S3 from 'aws-sdk/clients/s3';
@Injectable({
providedIn: 'root'
})
export class UploadService {
constructor() { }
uploadImage(file: any) {
const contentType = file.type;
const bucket = new S3({
accessKeyId: 'access-key',
secretAccessKey: 'secret-access-key',
region: 'region'
});
const fileName = 'images/' + file.name;
const params = {
Bucket: 'bucket',
Key: fileName,
Body: file,
ACL: 'public-read',
ContentType: contentType
};
bucket.upload(params, function(err: any, data: any){
if (err) {
console.log('There was an error uploading your file: ', err);
return false;
}
console.log('Successfully uploaded file.', data);
return true;
});
}
uploadDoc(file: any) {
const contentType = file.type;
const bucket = new S3({
accessKeyId: 'access-key',
secretAccessKey: 'secret-access-key',
region: 'region'
});
const fileName = 'documents/' + file.name;
const params = {
Bucket: 'bucket',
Key: fileName,
Body: file,
ACL: 'public-read',
ContentType: contentType
};
bucket.upload(params, function(err: any, data: any){
if (err) {
console.log('There was an error uploading your file: ', err);
return false;
}
console.log('Successfully uploaded file.', data);
return true;
});
}
}
I've recently upgraded to Angular 15, however running this code led me to the following errors, which seemingly go on endlessly:
Warning: /Users/N/Desktop/Angular/TEST00/src/app/services/upload/upload.service.ts depends on 'aws-sdk/clients/s3'. CommonJS or AMD dependencies can cause optimization bailouts.
For more info see: https://angular.io/guide/build#configuring-commonjs-dependencies
Error: ../../../../node_modules/aws-sdk/clients/acm.d.ts:153:37 - error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
153 export type CertificateBodyBlob = Buffer|Uint8Array|Blob|string;
~~~~~~
Error: ../../../../node_modules/aws-sdk/clients/acm.d.ts:155:38 - error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
155 export type CertificateChainBlob = Buffer|Uint8Array|Blob|string;
~~~~~~
Error: ../../../../node_modules/aws-sdk/clients/acm.d.ts:580:32 - error TS2591: Cannot find name 'Buffer'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
580 export type PassphraseBlob = Buffer|Uint8Array|Blob|string;
~~~~~~
So as anyone would today, I turned to ChatGPT to bright out solutions which recommended installing @aws-sdk/client-s3 v3.750.0 and the following optimised code:
import { Injectable } from '@angular/core';
import { S3Client, PutObjectCommand, ObjectCannedACL } from '@aws-sdk/client-s3';
@Injectable({
providedIn: 'root'
})
export class UploadService {
private s3: S3Client;
constructor() {
this.s3 = new S3Client({
region: 'region',
credentials: {
accessKeyId: 'access-key',
secretAccessKey: 'secret-access-key'
}
});
}
async uploadFile(file: File, folder: string) {
const fileName = `${folder}/${file.name}`;
const params = {
Bucket: 'bucket',
Key: fileName,
Body: file,
ACL: ObjectCannedACL.public_read,
ContentType: file.type
};
try {
const command = new PutObjectCommand(params);
const response = await this.s3.send(command);
console.log('Successfully uploaded:', response);
return response;
} catch (err) {
console.error('Error uploading file:', err);
throw err;
}
}
}
Which now gives the following error while trying to upload the file
Error uploading file: TypeError: readableStream.getReader is not a function
Where exactly am I going wrong in here? Is there a way I could maintain my old code which was well tried and tested in several projects, or how do I make the new more optimised code work?
If you need a hot fix, just add to client constuctor requestChecksumCalculation: "WHEN_REQUIRED"
const client = new S3({
// ... other params
requestChecksumCalculation: "WHEN_REQUIRED",
});
For more details see The GitHub issue about this bug