diff --git a/db/docker-compose.yml b/db/docker-compose.yml new file mode 100644 index 0000000..d6407f1 --- /dev/null +++ b/db/docker-compose.yml @@ -0,0 +1,13 @@ +version: '3.8' +services: + rethinkdb: + image: rethinkdb:latest + restart: unless-stopped + volumes: + - rethinkdb_data:/data + ports: + - "28015:28015" # Client driver port + - "8080:8080" # Admin UI port + +volumes: + rethinkdb_data: \ No newline at end of file diff --git a/frontend/src/app/upload/upload.component.ts b/frontend/src/app/upload/upload.component.ts index 770c0d9..fb8f4e1 100644 --- a/frontend/src/app/upload/upload.component.ts +++ b/frontend/src/app/upload/upload.component.ts @@ -2,6 +2,7 @@ import {Component, ElementRef, ViewChild} from '@angular/core'; import {NgIf} from "@angular/common"; import {FormatFileSizePipePipe} from "../format-file-size-pipe.pipe"; import {FormsModule} from "@angular/forms"; +import axios from "axios"; @Component({ selector: 'app-upload', @@ -28,6 +29,10 @@ export class UploadComponent { uploadProgress = 0; uploadFinished = false; + constructor() { + this.uploadSpeedTest(); + } + /** * Manages the file input click or drag and drop */ @@ -75,4 +80,55 @@ export class UploadComponent { } } + + private uploadSpeedTest() { + const start = new Date().getTime(); // Start timer + + // Create a 1MB payload for upload + const payload = new ArrayBuffer(1024 * 1024); // 1MB + const uint8View = new Uint8Array(payload); + for (let i = 0; i < uint8View.length; i++) { + uint8View[i] = 0; + } + + axios({ + method: 'post', + url: 'http://localhost/api/v1/upload-speed-test', + data: uint8View, + headers: { + 'Content-Type': 'application/octet-stream', + 'Access-Control-Allow-Origin': '*', // Allow CORS + }, + onUploadProgress: function(progressEvent) { + // Optional: handle progress events for feedback + } + }) + .then(response => { + const end = new Date().getTime(); // End timer + const duration = (end - start) / 1000; // Convert ms to seconds + const bitsUploaded = payload.byteLength * 8; + const speedBps = bitsUploaded / duration; + const speedKbps = speedBps / 1024; + const speedMbps = speedKbps / 1024; + console.log(`Upload speed: ${speedMbps.toFixed(2)} Mbps`); + }) + .catch(error => { + console.error('Error during upload test:', error); + }); + } + + /** + * Calculates the estimated upload time. + * @param {number} fileSize - The size of the file in bytes. + * @param {number} uploadSpeed - The upload speed in bytes per second. + * @returns {number} The estimated upload time in seconds. + */ + private calculateEstimatedUploadTime(fileSize: number, uploadSpeed: number) { + if (uploadSpeed <= 0) { + console.error("Upload speed must be greater than 0."); + return NaN; + } + const estimatedTimeInSeconds = fileSize / uploadSpeed; + return estimatedTimeInSeconds; + } } diff --git a/src/main/java/de/w665/sharepulse/config/CorsConfig.java b/src/main/java/de/w665/sharepulse/config/CorsConfig.java index e9f9fb6..37f5971 100644 --- a/src/main/java/de/w665/sharepulse/config/CorsConfig.java +++ b/src/main/java/de/w665/sharepulse/config/CorsConfig.java @@ -14,7 +14,7 @@ public class CorsConfig implements WebMvcConfigurer { public void addCorsMappings(CorsRegistry registry) { System.out.println("CORS CONFIGURATION ENABLED | DEVELOPMENT PROFILE"); System.out.println("IF YOU SEE THIS MESSAGE IN PRODUCTION, PLEASE DISABLE DEVELOPEMENT MODE IN APPLICATION.PROPERTIES"); - registry.addMapping("/api/v1/speed-test") + registry.addMapping("/api/v1/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*"); diff --git a/src/main/java/de/w665/sharepulse/rest/mappings/SpeedTest.java b/src/main/java/de/w665/sharepulse/rest/mappings/SpeedTest.java index 8a3a71c..35345d8 100644 --- a/src/main/java/de/w665/sharepulse/rest/mappings/SpeedTest.java +++ b/src/main/java/de/w665/sharepulse/rest/mappings/SpeedTest.java @@ -1,12 +1,16 @@ package de.w665.sharepulse.rest.mappings; import de.w665.sharepulse.rest.ApiRestController; +import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.io.InputStream; @Slf4j @RestController @@ -30,4 +34,23 @@ public class SpeedTest extends ApiRestController { return; } } + + @PostMapping("/upload-speed-test") + public void uploadSpeedTest(HttpServletRequest request, HttpServletResponse response) { + final int maxBytes = 1024 * 1024; // Limit to 1MB + byte[] buffer = new byte[1024]; // Buffer to read data + int bytesRead; + int totalBytesRead = 0; + + try (InputStream inputStream = request.getInputStream()) { + while ((bytesRead = inputStream.read(buffer)) != -1 && totalBytesRead < maxBytes) { + totalBytesRead += bytesRead; + } + response.setStatus(HttpServletResponse.SC_OK); + } catch (IOException e) { + log.error("Upload speed test failed.", e); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } + }