Skip to content

Commit

Permalink
profile photo
Browse files Browse the repository at this point in the history
  • Loading branch information
asadsahi committed Nov 17, 2017
1 parent 748a400 commit 733b668
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 63 deletions.
2 changes: 1 addition & 1 deletion ClientApp/app/account/+profile/profile.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { OtherAccountsComponent } from './other-accounts';
UserInfoComponent,
UpdatePasswordComponent,
UserPhotoComponent,
OtherAccountsComponent
OtherAccountsComponent,
],
providers: [ProfileService]
})
Expand Down
1 change: 1 addition & 0 deletions ClientApp/app/account/+profile/profile.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { OtherAccountsComponent } from './other-accounts';
const routes: Routes = [
{
path: '', component: ProfileComponent, children: [
{ path: '', redirectTo: 'userinfo' },
{ path: 'userinfo', component: UserInfoComponent },
{ path: 'updatepassword', component: UpdatePasswordComponent },
{ path: 'userphoto', component: UserPhotoComponent },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
<div class="row justify-content-center">
<figure class="figure">
<img [src]="selectedImage?.url ? selectedImage.url : profilePicture" class="figure-img img-fluid rounded" style="width: 200px;height: 200px;">
<img [src]="selectedImage?.url || existingImage" class="figure-img img-fluid rounded" style="width: 200px;height: 200px;">
<figcaption class="figure-caption text-right">{{selectedImage?.name}}</figcaption>
</figure>
</div>

<div class="row justify-content-center">
<input type="file" id="file" *ngIf="!selectedImage" (change)="fileChange($event)">
</div>

<div class="row justify-content-center" *ngIf="selectedImage">
<button type="button" class="btn btn-warning" (click)="cancel()">Cancel</button>
<button type="button" class="btn btn-primary" (click)="upload()">Use this</button>
<div class="row justify-content-center" *ngIf="!selectedImage">
<label class="custom-file">
<input type="file" id="file" class="custom-file-input" (change)="fileChange($event)">
<span class="custom-file-control"></span>
</label>
</div>

{{selectedImage | json}}
<div class="row justify-content-center">
<div class="btn-group" *ngIf="selectedImage">
<button type="button" class="btn btn-secondary" (click)="cancel()">Cancel</button>
<button type="button" class="btn btn-primary" (click)="upload()">Use this</button>
</div>
</div>
55 changes: 30 additions & 25 deletions ClientApp/app/account/+profile/user-photo/user-photo.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

import { DataService, NotificationsService } from '@app/core';

Expand All @@ -9,48 +8,54 @@ import { DataService, NotificationsService } from '@app/core';
styleUrls: ['./user-photo.component.scss']
})
export class UserPhotoComponent implements OnInit {
profilePicture: any = '';
public URL = 'api/manage/photo';
existingImage: any;
selectedImage: any;
filesToUpload: any;
imageToUpload: any;

constructor(
private dataService: DataService,
private ns: NotificationsService,
private http: HttpClient

private ns: NotificationsService
) { }

ngOnInit() {
this.dataService.getImage('api/manage/photo').subscribe(pic => {
this.profilePicture = pic;
});
this.getImage();
}

fileChange(event: any) {
const fileList: FileList = event.target.files;
if (fileList.length > 0) {
const file: File = fileList[0];
const formData: FormData = new FormData();
formData.append('uploadFile', file, file.name);
/** No need to include Content-Type in Angular 4 */
const headers = new HttpHeaders();
headers.append('Content-Type', 'multipart/form-data');
headers.append('Accept', 'application/json');
this.http.post(`api/manage/photo`, formData, { headers: headers })
.subscribe(res => this.ns.success('Upload successfull'));
if (event.target.files && event.target.files[0]) {
this.imageToUpload = event.target.files[0];
const reader = new FileReader();
reader.onload = (e: any) => {
this.selectedImage = {
mimetype: e.target.result.split(',')[0].split(':')[1].split(';')[0],
url: e.target.result
};
};
reader.readAsDataURL(this.imageToUpload);
}
}

upload() {
this.dataService.post('api/manage/photo', this.filesToUpload)
.subscribe(image => {
this.selectedImage = null;
this.ns.success('Success', 'Image changed successfully');
const file = new FormData();
file.append('file', this.imageToUpload);

this.dataService
.post(this.URL, file)
.subscribe(res => {
this.ns.success('Success', 'Image changed successfully');
this.existingImage = this.selectedImage.url;
this.selectedImage = undefined;
});
}

cancel() {
this.selectedImage = undefined;
}

private getImage() {
this.dataService.getImage(this.URL)
.subscribe(base64String => {
this.existingImage = 'data:image/png;base64,' + base64String;
});
}
}
4 changes: 2 additions & 2 deletions ClientApp/app/core/services/global-error.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ErrorHandler, Injectable, ApplicationRef, Injector } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http/src/response';

import { NotificationsService } from '../simple-notifications';
import { UtilityService } from './utility.service';
Expand All @@ -9,7 +8,7 @@ export class GlobalErrorHandler implements ErrorHandler {

constructor(private ns: NotificationsService, private inj: Injector) { }

handleError(errorResponse: HttpErrorResponse): void {
handleError(errorResponse: any): void {
if (errorResponse.status === 401) {
this.ns.error('Unauthorised', 'Pleae login again.');
this.inj.get(ApplicationRef).tick();
Expand All @@ -20,6 +19,7 @@ export class GlobalErrorHandler implements ErrorHandler {
this.ns.error(errorResponse.error.message, us.formatErrors(errorResponse.error.errors));
this.inj.get(ApplicationRef).tick();
}
this.ns.error(errorResponse);
// IMPORTANT: Don't Rethrow the error otherwise it will not emit errors after once
// https://stackoverflow.com/questions/44356040/angular-global-error-handler-working-only-once
// throw errorResponse;
Expand Down
52 changes: 27 additions & 25 deletions Server/Controllers/api/ManageController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,44 +259,46 @@ public IActionResult UserPhoto()
return NotFound();
}

return File(profileImage.Content, profileImage.ContentType);
return Ok(Convert.ToBase64String(profileImage.Content));
}

[HttpPost("photo")]
public async Task<IActionResult> UserPhoto(IFormFile file)
{
if (string.IsNullOrEmpty(file?.ContentType) || (file.Length == 0)) return BadRequest(new ApiError("Image provided is invalid"));
{
if (string.IsNullOrEmpty(file?.ContentType) || (file.Length == 0)) return BadRequest(new ApiError("Image provided is invalid"));

var size = file.Length;
var size = file.Length;

if (size > Convert.ToInt64(Startup.Configuration["MaxImageUploadSize"])) return BadRequest(new ApiError("Image size greater than allowed size"));
if (size > Convert.ToInt64(Startup.Configuration["MaxImageUploadSize"])) return BadRequest(new ApiError("Image size greater than allowed size"));

using (var memoryStream = new MemoryStream())
{
var existingImage = _context.ApplicationUserPhotos.FirstOrDefault(i => i.ApplicationUserId == User.GetUserId());
using (var memoryStream = new MemoryStream())
{
var existingImage = _context.ApplicationUserPhotos.FirstOrDefault(i => i.ApplicationUserId == User.GetUserId());

await file.CopyToAsync(memoryStream);
await file.CopyToAsync(memoryStream);

if (existingImage == null)
{
var userImage = new ApplicationUserPhoto
if (existingImage == null)
{
ContentType = file.ContentType,
Content = memoryStream.ToArray(),
ApplicationUserId = User.GetUserId()
};
_context.ApplicationUserPhotos.Add(userImage);
}
else
{
existingImage.ContentType = file.ContentType;
existingImage.Content = memoryStream.ToArray();
_context.ApplicationUserPhotos.Update(existingImage);
var userImage = new ApplicationUserPhoto
{
ContentType = file.ContentType,
Content = memoryStream.ToArray(),
ApplicationUserId = User.GetUserId()
};
_context.ApplicationUserPhotos.Add(userImage);
}
else
{
existingImage.ContentType = file.ContentType;
existingImage.Content = memoryStream.ToArray();
_context.ApplicationUserPhotos.Update(existingImage);
}
await _context.SaveChangesAsync();
}
await _context.SaveChangesAsync();
}

return NoContent();
return NoContent();
}
}

#region Helpers
Expand Down
3 changes: 2 additions & 1 deletion Server/Extensions/IdentityExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Security.Claims;
using AspNet.Security.OpenIdConnect.Primitives;

namespace AspNetCoreSpa.Server.Extensions
{
Expand All @@ -10,7 +11,7 @@ public static int GetUserId(this ClaimsPrincipal principal)
if (principal == null)
throw new ArgumentNullException(nameof(principal));

var id = principal.FindFirst(ClaimTypes.NameIdentifier)?.Value;
var id = principal.FindFirst(OpenIdConnectConstants.Claims.Subject)?.Value;

return Convert.ToInt32(id);
}
Expand Down

0 comments on commit 733b668

Please sign in to comment.