I am currently following this tutorial to upload an image directly from my angular application onto an AWS S3 bucket. I made some minor changes to sort out the few errors that came up during my execution, however when I run my code I find that the function I use to select the image ("selectFile()") is not being executed when I click the button.
The code in my appcomponent.ts file is as follows:
export class AppComponent {
selectedFiles: any = ''; //In the tutorial it was selectedFiles: FileList; But it kept throwing errors.
imageSrc: string = '';
constructor(private uploadService: UploadService) { }
ngOnInit() {
}
upload() {
const file = this.selectedFiles.item(0);
this.uploadService.uploadFile(file);
}
selectFile(event: any) {
const reader = new FileReader();
if(event.target.files && event.target.files.length) {
const [file] = event.target.files;
console.log(file.name);
reader.readAsDataURL(file);
reader.onload = () => {
this.imageSrc = reader.result as string;
}
this.selectedFiles = file;
}
}
}
UploadService:
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() { }
uploadFile(file: any) {
const contentType = file.type;
const bucket = new S3({
accessKeyId: '...',
secretAccessKey: '...',
region: '...'
});
const params = {
Bucket: '...',
Key: file.name,
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;
});
//for upload progress
/*bucket.upload(params).on('httpUploadProgress', function (evt) {
console.log(evt.loaded ' of ' evt.total ' Bytes');
}).send(function (err, data) {
if (err) {
console.log('There was an error uploading your file: ', err);
return false;
}
console.log('Successfully uploaded file.', data);
return true;
});*/
}
}
And AppComponent.html is below:
<label >
<img [src]="imageSrc" *ngIf="imageSrc" style="width:100%">
<input type="file" (change)="selectFile($event)">
</label>
<button [disabled]="!selectedFiles" (click)="upload()">Upload</button>
Where am I going wrong?
CodePudding user response:
You're taking the first file out of the file list twice:
const [file] = event.target.files; // taking the first file
and then again inside the upload
function:
const file = this.selectedFiles.item(0);
Also, it looks like you're mixing this.selectedFiles
(which the name and your tutorial imply should be a list of files, and for some reason you're intializing it to an empty string!) and you assign to it type File inside selectFile
.
I think it would be better to work with strong types, where I would change the .html and .ts as below:
.html:
<label >
<img [src]="imageSrc" *ngIf="imageSrc" style="width:100%">
<input type="file" (change)="selectFile($event.target.files)">
</label>
<button [disabled]="!selectedFileToUpload" (click)="upload()">Upload</button>
and .ts:
private selectedFileToUpload: File = null;
public upload() {
if (!this.selectedFileToUpload) {
alert('Please select a file first!'); // or any other message to the user to choose a file
return;
}
this.uploadService.uploadFile(this.selectedFileToUpload);
}
public selectFile(filesList: FileList) {
var reader = new FileReader();
const fileToUpload = filesList.item(0);
console.log(fileToUpload.name);
reader.readAsDataURL(fileToUpload);
reader.onload = () => {
this.imageSrc = reader.result as string;
};
this.selectedFileToUpload = fileToUpload;
}
Note,
however when I run my code I find that the function I use to select the image ("selectFile()") is not being executed when I click the button.
The selectFile
function should not be executed when you click the upload button! The selectFile
function will be executed every time you change a file in the selected files, and in the example I wrote (not tested) it should save a reference to the file you want to upload. Then, the Upload
button would only trigger the upload
function that would take the same reference to the selected file and pass it to the upload service to be uploaded by the s3 package.
Again, I didn't test the code, but I tried to help by fixing your logic.