fix bugs and add html page
This commit is contained in:
@ -34,10 +34,9 @@ public class S3FileHandler {
|
||||
}).get();
|
||||
}
|
||||
|
||||
public ServerResponse downloadFile(ServerRequest request) throws ServletException, IOException {
|
||||
return Optional.of(request.body(DirectoryPath.class))
|
||||
.map(DirectoryPath::path)
|
||||
.map(URI::toString)
|
||||
public ServerResponse downloadFile(ServerRequest request) {
|
||||
return Optional.of(request.pathVariable("path").substring(1))
|
||||
.map(URI::create)
|
||||
.map(service::downloadFile)
|
||||
.map(reader -> {
|
||||
try (reader) {
|
||||
@ -75,9 +74,9 @@ public class S3FileHandler {
|
||||
.get();
|
||||
}
|
||||
|
||||
public ServerResponse listing(ServerRequest request) throws ServletException, IOException {
|
||||
return Optional.of(request.body(DirectoryPath.class))
|
||||
.map(key -> service.listing(key.path()))
|
||||
public ServerResponse listing(ServerRequest request) {
|
||||
return Optional.of(request.pathVariable("path").substring(1))
|
||||
.map(key -> service.listing(URI.create(key)))
|
||||
.map(objects -> ServerResponse.ok().body(objects))
|
||||
.get();
|
||||
}
|
||||
|
@ -2,21 +2,23 @@ package ua.com.dxrkness.controller;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import org.springframework.web.servlet.function.RouterFunction;
|
||||
import org.springframework.web.servlet.function.RouterFunctions;
|
||||
import org.springframework.web.servlet.function.ServerResponse;
|
||||
|
||||
@Configuration
|
||||
public class S3FileHandlerConfig {
|
||||
public class S3FileHandlerConfig implements WebMvcConfigurer {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> router(S3FileHandler handler) {
|
||||
return RouterFunctions.route()
|
||||
.path("/files", b -> b
|
||||
.GET(handler::downloadFile)
|
||||
.GET("/{*path}", handler::downloadFile)
|
||||
.POST(handler::uploadFile)
|
||||
)
|
||||
.path("/dirs", b -> b
|
||||
.GET(handler::listing)
|
||||
.GET("/{*path}", handler::listing)
|
||||
.POST(handler::createDirectory)
|
||||
)
|
||||
.path("/common", b -> b
|
||||
@ -25,4 +27,12 @@ public class S3FileHandlerConfig {
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedMethods("*")
|
||||
.allowedHeaders("*")
|
||||
.allowedOriginPatterns("*");
|
||||
}
|
||||
}
|
@ -14,7 +14,6 @@ import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
@ -108,12 +107,12 @@ public class S3Service {
|
||||
RequestBody.fromInputStream(file.getInputStream(), file.getSize()));
|
||||
}
|
||||
|
||||
public BufferedInputStream downloadFile(String key) {
|
||||
public BufferedInputStream downloadFile(URI key) {
|
||||
return new BufferedInputStream(
|
||||
Channels.newInputStream(
|
||||
Channels.newChannel(client.getObject(b -> b
|
||||
.bucket(bucketName)
|
||||
.key(key)))));
|
||||
.key(key.toString())))));
|
||||
}
|
||||
|
||||
public List<String> listBuckets() {
|
||||
|
255
static/common.html
Normal file
255
static/common.html
Normal file
@ -0,0 +1,255 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Unified</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Unified</h1>
|
||||
|
||||
<div>
|
||||
<h2>Current Directory: <span id="currentPath">/</span></h2>
|
||||
<button onclick="goToParent()">Parent Directory</button>
|
||||
<button onclick="refreshDirectory()">Refresh</button>
|
||||
<input type="text" id="newDirName" placeholder="New directory name">
|
||||
<button onclick="createDirectoryHere()">Create Directory</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Directory Contents</h3>
|
||||
<div id="directoryContents">Loading...</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>File Operations</h3>
|
||||
<input type="file" id="fileUpload">
|
||||
<button onclick="uploadFileHere()">Upload to Current Directory</button>
|
||||
<div id="fileOperationResult"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3>Navigation</h3>
|
||||
<input type="text" id="pathInput" placeholder="Enter path to navigate to">
|
||||
<button onclick="navigateToPath()">Go to Path</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const baseUrl = 'http://localhost:8080';
|
||||
let currentPath = '';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
refreshDirectory();
|
||||
});
|
||||
|
||||
function updateCurrentPathDisplay() {
|
||||
document.getElementById('currentPath').textContent = currentPath;
|
||||
document.getElementById('pathInput').value = currentPath;
|
||||
}
|
||||
|
||||
async function refreshDirectory() {
|
||||
const contentsDiv = document.getElementById('directoryContents');
|
||||
contentsDiv.innerHTML = 'Loading...';
|
||||
|
||||
try {
|
||||
const response = await fetch(`${baseUrl}/dirs/${decodeURIComponent(currentPath)}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
displayDirectoryContents(data);
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
contentsDiv.innerHTML = `<p style="color: red;">Error loading directory: ${response.status} - ${errorText}</p>`;
|
||||
}
|
||||
} catch (error) {
|
||||
contentsDiv.innerHTML = `<p style="color: red;">Network error: ${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
function displayDirectoryContents(items) {
|
||||
const contentsDiv = document.getElementById('directoryContents');
|
||||
|
||||
if (!Array.isArray(items) || items.length === 0) {
|
||||
contentsDiv.innerHTML = '<p>Directory is empty</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
let html = '<table border="1">';
|
||||
html += '<tr><th>Name</th><th>Type</th><th>Actions</th></tr>';
|
||||
|
||||
items.forEach(item => {
|
||||
const isDirectory = item.endsWith('/');
|
||||
const name = item;
|
||||
const fullPath = item;
|
||||
|
||||
html += '<tr>';
|
||||
html += `<td>${name}</td>`;
|
||||
html += `<td>${isDirectory ? 'Directory' : 'File'}</td>`;
|
||||
html += '<td>';
|
||||
|
||||
if (isDirectory) {
|
||||
html += `<button onclick="navigateToDirectory('${fullPath}')">Open</button> `;
|
||||
} else {
|
||||
html += `<button onclick="downloadFileFromPath('${fullPath}')">Download</button> `;
|
||||
}
|
||||
|
||||
html += `<button onclick="removeItem('${fullPath}')" style="color: red;">Delete</button>`;
|
||||
html += '</td>';
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
html += '</table>';
|
||||
contentsDiv.innerHTML = html;
|
||||
}
|
||||
|
||||
function navigateToDirectory(path) {
|
||||
currentPath = path;
|
||||
updateCurrentPathDisplay();
|
||||
refreshDirectory();
|
||||
}
|
||||
|
||||
function navigateToPath() {
|
||||
const path = document.getElementById('pathInput').value;
|
||||
navigateToDirectory(path);
|
||||
}
|
||||
|
||||
function goToParent() {
|
||||
if (currentPath !== '') {
|
||||
const parts = currentPath.split('/').filter(p => p);
|
||||
parts.pop();
|
||||
currentPath = parts.length > 0 ? '' + parts.join('/') + '/' : '';
|
||||
updateCurrentPathDisplay();
|
||||
refreshDirectory();
|
||||
}
|
||||
}
|
||||
|
||||
async function createDirectoryHere() {
|
||||
const dirName = document.getElementById('newDirName').value;
|
||||
const resultDiv = document.getElementById('fileOperationResult');
|
||||
|
||||
if (!dirName) {
|
||||
resultDiv.innerHTML = '<p style="color: red;">Please enter a directory name</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
const newDirPath = currentPath === '' ? `${dirName}/` : `${currentPath}${dirName}/`;
|
||||
|
||||
try {
|
||||
const response = await fetch(`${baseUrl}/dirs`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ path: newDirPath })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
resultDiv.innerHTML = `<p style="color: green;">Directory created: ${dirName}</p>`;
|
||||
document.getElementById('newDirName').value = '';
|
||||
await refreshDirectory();
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
resultDiv.innerHTML = `<p style="color: red;">Error: ${response.status} - ${errorText}</p>`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<p style="color: red;">Network error: ${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadFileHere() {
|
||||
const fileInput = document.getElementById('fileUpload');
|
||||
const resultDiv = document.getElementById('fileOperationResult');
|
||||
|
||||
if (!fileInput.files[0]) {
|
||||
resultDiv.innerHTML = '<p style="color: red;">Please select a file</p>';
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileInput.files[0];
|
||||
const filePath = currentPath === '/' ? `/${file.name}` : `${currentPath}/${file.name}`;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
formData.append('dirPath', JSON.stringify({ path: filePath }));
|
||||
|
||||
try {
|
||||
resultDiv.innerHTML = '<p>Uploading...</p>';
|
||||
|
||||
const response = await fetch(`${baseUrl}/files`, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
resultDiv.innerHTML = `<p style="color: green;">File uploaded: ${file.name}</p>`;
|
||||
fileInput.value = '';
|
||||
await refreshDirectory();
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
resultDiv.innerHTML = `<p style="color: red;">Error: ${response.status} - ${errorText}</p>`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<p style="color: red;">Network error: ${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadFileFromPath(filePath) {
|
||||
const resultDiv = document.getElementById('fileOperationResult');
|
||||
|
||||
try {
|
||||
resultDiv.innerHTML = '<p>Downloading...</p>';
|
||||
|
||||
const response = await fetch(`${baseUrl}/files/${decodeURIComponent(filePath)}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const blob = await response.blob();
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = filePath.split('/').pop() || 'download';
|
||||
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
|
||||
resultDiv.innerHTML = `<p style="color: green;">File downloaded successfully</p>`;
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
resultDiv.innerHTML = `<p style="color: red;">Error: ${response.status} - ${errorText}</p>`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<p style="color: red;">Network error: ${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
|
||||
async function removeItem(path) {
|
||||
const resultDiv = document.getElementById('fileOperationResult');
|
||||
|
||||
try {
|
||||
const response = await fetch(`${baseUrl}/common`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ path: path })
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
resultDiv.innerHTML = `<p style="color: green;">Successfully removed: ${path}</p>`;
|
||||
await refreshDirectory();
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
resultDiv.innerHTML = `<p style="color: red;">Error: ${response.status} - ${errorText}</p>`;
|
||||
}
|
||||
} catch (error) {
|
||||
resultDiv.innerHTML = `<p style="color: red;">Network error: ${error.message}</p>`;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user