Add object upload feature to console

This commit is contained in:
biondizzle
2025-06-05 19:54:51 -04:00
parent fab814e179
commit 9684406295
2 changed files with 83 additions and 5 deletions

View File

@@ -277,6 +277,34 @@ class ConsoleApiController extends AbstractController
]);
}
if ($request->getMethod() === 'POST') {
$objectKey = $request->headers->get('X-Object-Key')
?? $request->query->get('key')
?? $request->request->get('object_key');
if (empty($objectKey)) {
return new JsonResponse(['error' => 'Missing object key'], 400);
}
$contentType = $request->headers->get('Content-Type', 'application/octet-stream');
$file = $request->files->get('file');
if ($file instanceof \Symfony\Component\HttpFoundation\File\UploadedFile) {
$contentType = $file->getMimeType() ?: $contentType;
$content = file_get_contents($file->getPathname());
} else {
$content = $request->getContent();
}
$object = $this->s3Service->putObject($bucket, $objectKey, $content, $contentType);
return new JsonResponse([
'key' => $object->getObjectKey(),
'etag' => $object->getEtag(),
'size' => $object->getSize(),
'content_type' => $object->getContentType()
], 201);
}
if ($request->getMethod() === 'DELETE') {
$data = json_decode($request->getContent(), true);
$keys = $data['keys'] ?? [];

View File

@@ -529,9 +529,12 @@
<div x-show="selectedBucket" class="card">
<div class="card-header">
Objects
<div>
<input x-model="objectSearch" @input="filterObjects()"
<div style="display: flex; gap: 0.5rem;">
<input x-model="objectSearch" @input="filterObjects()"
placeholder="Search objects..." class="search-input">
<button @click="showUploadModal = true" class="btn btn-primary btn-sm">
<i class="fas fa-upload"></i> Upload
</button>
</div>
</div>
<div class="card-body">
@@ -630,6 +633,27 @@
</div>
</div>
<!-- Upload Object Modal -->
<div x-show="showUploadModal" x-cloak class="modal" @click.self="showUploadModal = false">
<div class="modal-content">
<h3 style="margin-bottom: 1rem;">Upload Object</h3>
<form @submit.prevent="uploadObject()">
<div class="form-group">
<label class="form-label">Object Key</label>
<input x-model="uploadKey" type="text" class="form-input" placeholder="path/to/file.txt" required>
</div>
<div class="form-group">
<label class="form-label">Select File</label>
<input type="file" @change="uploadFile = $event.target.files[0]" class="form-input" required>
</div>
<div style="display: flex; gap: 1rem; justify-content: flex-end;">
<button type="button" @click="showUploadModal = false" class="btn btn-secondary">Cancel</button>
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</form>
</div>
</div>
<!-- Create Credential Modal -->
<div x-show="showCreateCredentialModal" x-cloak class="modal" @click.self="showCreateCredentialModal = false">
<div class="modal-content">
@@ -775,6 +799,7 @@
showCreateCredentialModal: false,
showCreateBucketModal: false,
showCreatePresignedModal: false,
showUploadModal: false,
// Forms
newCredential: {
@@ -794,6 +819,8 @@
expires_in: 3600,
access_key: ''
},
uploadFile: null,
uploadKey: '',
init() {
this.loadStats();
@@ -991,10 +1018,10 @@
async deleteObject(bucketName, objectKey) {
if (!confirm('Are you sure you want to delete this object?')) return;
try {
await this.apiCall(`/buckets/${bucketName}/objects/${encodeURIComponent(objectKey)}`, {
method: 'DELETE'
await this.apiCall(`/buckets/${bucketName}/objects/${encodeURIComponent(objectKey)}`, {
method: 'DELETE'
});
this.showMessage('Object deleted successfully!');
this.viewBucket(bucketName);
@@ -1003,6 +1030,29 @@
}
},
async uploadObject() {
if (!this.uploadFile || !this.uploadKey) return;
try {
await fetch(`/api/buckets/${this.selectedBucket.name}/objects?key=${encodeURIComponent(this.uploadKey)}`, {
method: 'POST',
headers: {
'Content-Type': this.uploadFile.type || 'application/octet-stream',
'X-Object-Key': this.uploadKey
},
body: this.uploadFile
});
this.showMessage('Object uploaded successfully!');
this.showUploadModal = false;
this.uploadFile = null;
this.uploadKey = '';
this.viewBucket(this.selectedBucket.name);
} catch (error) {
console.error('Failed to upload object:', error);
this.showMessage('Upload failed', 'error');
}
},
async viewCredential(credential) {
// Could open a modal with full credential details
alert(`Access Key: ${credential.access_key}\nUser: ${credential.user_name || 'N/A'}\nStatus: ${credential.is_active ? 'Active' : 'Inactive'}`);