uploading picture from flutter to webapi implemented

This commit is contained in:
LilleBRG 2024-09-09 15:36:32 +02:00
parent c43144e028
commit 873fd44f1c
9 changed files with 140 additions and 77 deletions

View File

@ -26,7 +26,7 @@ namespace API.Application.Users.Queries
Id = user.Id,
Email = user.Email,
Username = user.Username,
ProfilePictureURL = user.ProfilePicture,
ProfilePicture = user.ProfilePicture,
}).ToList();
return userDTOs;
}

View File

@ -24,7 +24,7 @@ namespace API.Application.Users.Queries
return new ConflictObjectResult(new { message = "No user on given Id" });
}
return new OkObjectResult(new { id = user.Id, email = user.Email, username = user.Username, profilePictureURL = user.ProfilePicture, createdAt = user.CreatedAt });
return new OkObjectResult(new { id = user.Id, email = user.Email, username = user.Username, profilePicture = user.ProfilePicture, createdAt = user.CreatedAt });
}

View File

@ -75,7 +75,7 @@ namespace API.Controllers
[Authorize]
[HttpPut]
public async Task<IActionResult> PutUser(UpdateUserDTO UpdateUserDTO)
public async Task<IActionResult> PutUser([FromForm ]UpdateUserDTO UpdateUserDTO)
{
return await _updateUser.Handle(UpdateUserDTO);
}

View File

@ -17,7 +17,7 @@ public class UserDTO
public string Id { get; set; }
public string Email { get; set; }
public string Username { get; set; }
public string ProfilePictureURL { get; set; }
public string ProfilePicture { get; set; }
}

View File

@ -29,6 +29,7 @@ namespace API.Persistence.Services
var request = new PutObjectRequest
{
InputStream = fileStream,
BucketName = "h4picturebucket",
Key = fileName,
DisablePayloadSigning = true
};
@ -40,7 +41,7 @@ namespace API.Persistence.Services
throw new AmazonS3Exception($"Error uploading file to S3. HTTP Status Code: {response.HttpStatusCode}");
}
var imageUrl = $"https://pub-bf709b641048489ca70f693673e3e04c.r2.dev/{fileName}";
var imageUrl = $"https://pub-bf709b641048489ca70f693673e3e04c.r2.dev/h4picturebucket/{fileName}";
return imageUrl;
}
}

View File

@ -1,4 +1,7 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
@ -63,6 +66,92 @@ Future<String?> request(BuildContext? context, ApiService service, String method
return utf8.decode(response.bodyBytes);
}
Future<String?> putUser(
BuildContext? context,
ApiService service,
String method,
String path,
Map<String, dynamic> body,
File? profilePicture // The image file
) async {
final messenger = context != null ? ScaffoldMessenger.of(context) : null;
final prefs = await SharedPreferences.getInstance();
final host = const String.fromEnvironment('AUTH_SERVICE_HOST');
final token = prefs.getString('token');
final Map<String, String> headers = {};
if (token != null) headers.addAll({'Authorization': 'Bearer $token'});
// Create the Uri
var uri = Uri.parse(host + path);
// Create a MultipartRequest
var request = http.MultipartRequest('PUT', uri);
request.headers.addAll(headers);
// Add form fields
request.fields['id'] = body['id'];
request.fields['username'] = body['username'];
request.fields['email'] = body['email'];
request.fields['password'] = body['password'];
// Attach the file to the request (if provided)
if (profilePicture != null) {
var fileStream = http.ByteStream(profilePicture.openRead());
var length = await profilePicture.length();
var multipartFile = http.MultipartFile(
'ProfilePicture', // field name matches your backend DTO
fileStream,
length,
filename: profilePicture.path.split('/').last,
);
request.files.add(multipartFile);
}
try {
// Send the request
var streamedResponse = await request.send();
var response = await http.Response.fromStream(streamedResponse);
// Handle non-success responses
if (response.statusCode < 200 || response.statusCode >= 300) {
try {
final json = jsonDecode(response.body);
messenger?.showSnackBar(SnackBar(content: Text(json['message'] ?? json['title'])));
debugPrint('API error: ' + json['message']);
} catch (e) {
debugPrint(e.toString());
messenger?.showSnackBar(SnackBar(content: Text('Something went wrong (HTTP ${response.statusCode})')));
}
return null;
}
return utf8.decode(response.bodyBytes);
} catch (e) {
debugPrint(e.toString());
messenger?.showSnackBar(const SnackBar(content: Text('Unable to connect to server')));
return null;
}
}
Future<File> _compressImage(File file) async {
final filePath = file.absolute.path;
final lastIndex = filePath.lastIndexOf(RegExp(r'.jp'));
final splitted = filePath.substring(0, lastIndex);
final outPath = "${splitted}_compressed.jpg";
var result = await FlutterImageCompress.compressAndGetFile(
file.absolute.path,
outPath,
quality: 80,
minWidth: 1024,
minHeight: 1024,
);
return File(result!.path);
}
Future<bool> isLoggedIn(BuildContext context) async {
final messenger = ScaffoldMessenger.of(context);
final prefs = await SharedPreferences.getInstance();

View File

@ -1,6 +1,5 @@
import 'dart:io';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mobile/models.dart';
@ -47,48 +46,22 @@ class _ProfilePageState extends State<EditProfilePage> {
}
Future _pickImageFromGallery() async{
final picker = ImagePicker();
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
if(image == null) {return;}
else{
File compressedFile = await _compressImage(File(image.path));
final image = await ImagePicker().pickImage(source: ImageSource.gallery);
if (image == null) return;
setState(() {
_selectedImage = compressedFile;
_selectedImage = File(image.path);
});
}
}
Future _pickImageFromCamera() async{
final picker = ImagePicker();
final XFile? image = await picker.pickImage(source: ImageSource.camera);
if(image == null) {return;}
else{
File compressedFile = await _compressImage(File(image.path));
final image = await ImagePicker().pickImage(source: ImageSource.camera);
if (image == null) return;
setState(() {
_selectedImage = compressedFile;
_selectedImage = File(image.path);
});
}
}
Future<File> _compressImage(File file) async {
final filePath = file.absolute.path;
final lastIndex = filePath.lastIndexOf(RegExp(r'.jp'));
final splitted = filePath.substring(0, lastIndex);
final outPath = "${splitted}_compressed.jpg";
var result = await FlutterImageCompress.compressAndGetFile(
file.absolute.path,
outPath,
quality: 80,
minWidth: 1024,
minHeight: 1024,
);
return File(result!.path);
}
void _saveProfile() async {
if (passwordInput.text != confirmPasswordInput.text) {
@ -100,37 +73,32 @@ class _ProfilePageState extends State<EditProfilePage> {
final prefs = await SharedPreferences.getInstance();
String? id = prefs.getString('id');
if (!mounted) {
return;
}
if (!mounted) return;
if (id != null) {
final response = await api.request(context, api.ApiService.auth, 'PUT', '/api/users', {
final response = await api.putUser(
context,
api.ApiService.auth,
'PUT',
'/api/users',
{
'id': id,
'username': usernameInput.text,
'email': emailInput.text,
'password': passwordInput.text,
'profilePicture': _selectedImage,
});
},
_selectedImage // Pass the selected image to the putUser function
);
if (!mounted) {
return;
}
if (!mounted) return;
if (response != null) {
User updatedUser = User(
id,
emailInput.text,
usernameInput.text,
_selectedImage,
DateTime.now(),
);
setState(() {
user = updatedUser;
user = null;
});
Navigator.of(context).pop(); // Close the dialog
Navigator.pushReplacementNamed(context, '/profile');
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Something went wrong! Please contact an admin.')),
@ -139,6 +107,7 @@ class _ProfilePageState extends State<EditProfilePage> {
}
}
void _deleteProfile(BuildContext context) {
showDialog(
context: context,

View File

@ -44,7 +44,7 @@ class User {
String id;
String email;
String username;
File? profilePicture;
String profilePicture;
DateTime createdAt;
User( this.id, this.email, this.username, this.profilePicture, this.createdAt);

View File

@ -41,6 +41,8 @@ class _ProfilePageState extends State<ProfilePage> {
Map<String, dynamic> json = jsonDecode(response);
User jsonUser = User.fromJson(json);
print(jsonUser.profilePicture);
setState(() {
userData = jsonUser;
user = jsonUser;
@ -71,11 +73,13 @@ class _ProfilePageState extends State<ProfilePage> {
: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
userData?.profilePicture != null ?
const Icon(
Icons.account_circle,
size: 100,
color: Colors.grey,
),
)
: Image(image: NetworkImage('https://pub-bf709b641048489ca70f693673e3e04c.r2.dev/h4picturebucket/PPb83569bef3b9470782d7b42bc4e552ff.png'), height: 100),
const SizedBox(height: 20),
Text(
userData!.username,