Bugfix
This commit is contained in:
+11
-13
@@ -38,12 +38,11 @@ async def get_upload_token(file_name: str, file_type: str, file_size: int, respo
|
|||||||
|
|
||||||
user_ip = request.client.host
|
user_ip = request.client.host
|
||||||
file_uuid = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
|
file_uuid = ''.join(random.choices(string.ascii_letters + string.digits, k=6))
|
||||||
async with s3_worker as worker:
|
try:
|
||||||
try:
|
post_data = await s3_worker.generate_upload_post(file_uuid, content_type=file_type)
|
||||||
post_data = await worker.generate_upload_post(file_name, content_type=file_type)
|
except Exception as exception:
|
||||||
except Exception as exception:
|
response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||||
response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
return BaseResponse(result="Error generating S3 access token. Error: " + str(exception), error=True)
|
||||||
return BaseResponse(result="Error generating S3 access token. Error: " + str(exception), error=True)
|
|
||||||
|
|
||||||
redis_worker.create_record(user_ip, file_name, file_uuid, file_type, datetime.now().isoformat(), file_size)
|
redis_worker.create_record(user_ip, file_name, file_uuid, file_type, datetime.now().isoformat(), file_size)
|
||||||
print(post_data)
|
print(post_data)
|
||||||
@@ -64,18 +63,17 @@ async def get_file_by_uuid(file_uuid:str, response: Response, request: Request)
|
|||||||
response.status_code = status.HTTP_400_BAD_REQUEST
|
response.status_code = status.HTTP_400_BAD_REQUEST
|
||||||
return BaseResponse(result={"data": None, "comment": "File with this UUID not found"}, error=True)
|
return BaseResponse(result={"data": None, "comment": "File with this UUID not found"}, error=True)
|
||||||
|
|
||||||
async with s3_worker as worker:
|
try:
|
||||||
try:
|
download_url = await s3_worker.generate_download_url(file_uuid, redis_data["file_name"])
|
||||||
download_url = await worker.generate_download_url(file_uuid, redis_data["file_name"])
|
except Exception as exception:
|
||||||
except Exception as exception:
|
response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||||
response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
|
return BaseResponse(result="Error generating S3 access token. Error: " + str(exception), error=True)
|
||||||
return BaseResponse(result="Error generating S3 access token. Error: " + str(exception), error=True)
|
|
||||||
|
|
||||||
return BaseResponse(result={"data": {"url": download_url, "file_name": redis_data["file_name"], "file_size": redis_data["file_size"]}, "comment": "Ok"})
|
return BaseResponse(result={"data": {"url": download_url, "file_name": redis_data["file_name"], "file_size": redis_data["file_size"]}, "comment": "Ok"})
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
config = uvicorn.Config("main:app", port=5000, host="0.0.0.0", log_level="debug")
|
config = uvicorn.Config("main:app", port=int(os.getenv('BACKEND_PORT')), host="0.0.0.0", log_level="debug")
|
||||||
server = uvicorn.Server(config)
|
server = uvicorn.Server(config)
|
||||||
await server.serve()
|
await server.serve()
|
||||||
|
|
||||||
|
|||||||
+43
-64
@@ -1,6 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from aiobotocore.session import get_session
|
from aiobotocore.session import get_session
|
||||||
@@ -10,84 +11,62 @@ class S3Worker:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
self._S3_ACCESS_KEY_ID = os.getenv('S3_ACCESS_KEY_ID')
|
self._s3_config = {
|
||||||
self._S3_SECRET_ACCESS_KEY = os.getenv('S3_SECRET_ACCESS_KEY')
|
"aws_access_key_id": os.getenv('S3_ACCESS_KEY_ID'),
|
||||||
self._S3_ENDPOINT_URL = os.getenv('S3_ENDPOINT_URL')
|
"aws_secret_access_key": os.getenv('S3_SECRET_ACCESS_KEY'),
|
||||||
|
"endpoint_url": os.getenv('S3_ENDPOINT_URL')
|
||||||
|
}
|
||||||
|
|
||||||
self._s3_session = get_session()
|
self._s3_session = get_session()
|
||||||
self._s3_client = None
|
|
||||||
|
|
||||||
self.bucket = os.getenv('BUCKET_NAME')
|
self.bucket = os.getenv('BUCKET_NAME')
|
||||||
self.max_file_size = os.getenv('MAX_FILES_SIZE')
|
self.max_file_size = os.getenv('MAX_FILES_SIZE')
|
||||||
|
|
||||||
async def __aenter__(self):
|
@asynccontextmanager
|
||||||
self._client = await self._s3_session.create_client(
|
async def get_client(self):
|
||||||
"s3",
|
async with self._s3_session.create_client("s3", **self._s3_config) as client:
|
||||||
region_name="us-east-1",
|
yield client
|
||||||
aws_access_key_id=self._S3_ACCESS_KEY_ID,
|
|
||||||
aws_secret_access_key=self._S3_SECRET_ACCESS_KEY,
|
|
||||||
endpoint_url=self._S3_ENDPOINT_URL,
|
|
||||||
).__aenter__()
|
|
||||||
return self
|
|
||||||
|
|
||||||
async def __aexit__(self, exc_type, exc, tb):
|
|
||||||
await self._client.__aexit__(exc_type, exc, tb)
|
|
||||||
|
|
||||||
|
|
||||||
async def upload_file(self, key: str, data: bytes):
|
|
||||||
await self._client.put_object(
|
|
||||||
Bucket=self.bucket,
|
|
||||||
Key=key,
|
|
||||||
Body=data,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def generate_upload_post(self, key: str, content_type: str, expires_in: int = 300) -> dict:
|
async def generate_upload_post(self, key: str, content_type: str, expires_in: int = 300) -> dict:
|
||||||
return await self._client.generate_presigned_post(
|
async with self.get_client() as client:
|
||||||
Bucket=self.bucket,
|
return await client.generate_presigned_post(
|
||||||
Key=key,
|
Bucket=self.bucket,
|
||||||
Fields={
|
Key=key,
|
||||||
"Content-Type": content_type,
|
Fields={
|
||||||
"acl": "private",
|
"Content-Type": content_type,
|
||||||
},
|
"acl": "private",
|
||||||
Conditions=[
|
},
|
||||||
["content-length-range", 0, self.max_file_size],
|
Conditions=[
|
||||||
{"acl": "private"},
|
["content-length-range", 0, self.max_file_size],
|
||||||
],
|
{"acl": "private"},
|
||||||
ExpiresIn=expires_in,
|
],
|
||||||
)
|
ExpiresIn=expires_in,
|
||||||
|
)
|
||||||
|
|
||||||
async def download_file(self, key: str):
|
|
||||||
return await self._client.get_object(
|
|
||||||
Bucket=self.bucket,
|
|
||||||
Key=key,
|
|
||||||
)
|
|
||||||
|
|
||||||
async def generate_download_url(self, key: str, filename: str, expires_in: int = 300) -> str:
|
async def generate_download_url(self, key: str, filename: str, expires_in: int = 300) -> str:
|
||||||
return await self._client.generate_presigned_url("get_object",
|
async with self.get_client() as client:
|
||||||
Params={
|
return await client.generate_presigned_url("get_object",
|
||||||
"Bucket": self.bucket,
|
Params={
|
||||||
"Key": key,
|
"Bucket": self.bucket,
|
||||||
"ResponseContentDisposition": (
|
"Key": key,
|
||||||
f'attachment; filename="{filename}"'
|
"ResponseContentDisposition": (
|
||||||
),
|
f'attachment; filename="{filename}"'
|
||||||
},
|
),
|
||||||
ExpiresIn=expires_in,
|
},
|
||||||
)
|
ExpiresIn=expires_in,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
s3_worker = S3Worker()
|
|
||||||
async def test_run():
|
async def test_run():
|
||||||
async with s3_worker as worker:
|
worker = S3Worker()
|
||||||
await worker.upload_file("test.txt", b"hello")
|
|
||||||
file = await worker.download_file("test.txt")
|
|
||||||
file_text = await file["Body"].read()
|
|
||||||
print(file_text)
|
|
||||||
|
|
||||||
url = await worker.generate_download_url("test.txt", "hello.txt")
|
url = await worker.generate_download_url("test.txt", "hello.txt")
|
||||||
print(url)
|
print(url)
|
||||||
url = await worker.generate_upload_post("some.jpg", content_type="image/jpeg")
|
url = await worker.generate_upload_post("some.jpg", content_type="image/jpeg")
|
||||||
print(url)
|
print(url)
|
||||||
url = await worker.generate_download_url("some.jpg", "image.jpg")
|
url = await worker.generate_download_url("some.jpg", "image.jpg")
|
||||||
print(url)
|
print(url)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
+5
-3
@@ -33,7 +33,7 @@ async function handleDownloadPage(fileUuid) {
|
|||||||
const downloadContent = document.getElementById('downloadContent');
|
const downloadContent = document.getElementById('downloadContent');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/get_download_link/${fileUuid}`);
|
const response = await fetch(`/api/get_download_link/${fileUuid}`);
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
if (data.error || !data.result || !data.result.data) {
|
if (data.error || !data.result || !data.result.data) {
|
||||||
@@ -73,7 +73,7 @@ function initUploadPage() {
|
|||||||
// Fetch max file size on page load
|
// Fetch max file size on page load
|
||||||
async function loadMaxFileSize() {
|
async function loadMaxFileSize() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/max_file_size');
|
const response = await fetch('/api/max_file_size');
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`Ошибка сервера: ${response.status}`);
|
throw new Error(`Ошибка сервера: ${response.status}`);
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ function initUploadPage() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Step 1: Get upload token
|
// Step 1: Get upload token
|
||||||
const tokenUrl = `/upload_token?file_name=${encodeURIComponent(file.name)}&file_type=${encodeURIComponent(file.type)}&file_size=${file.size}`;
|
const tokenUrl = `/api/upload_token?file_name=${encodeURIComponent(file.name)}&file_type=${encodeURIComponent(file.type)}&file_size=${file.size}`;
|
||||||
const tokenResponse = await fetch(tokenUrl);
|
const tokenResponse = await fetch(tokenUrl);
|
||||||
|
|
||||||
if (!tokenResponse.ok) {
|
if (!tokenResponse.ok) {
|
||||||
@@ -176,6 +176,8 @@ function initUploadPage() {
|
|||||||
|
|
||||||
const uploadData = tokenData.result.data;
|
const uploadData = tokenData.result.data;
|
||||||
const fileUuid = tokenData.result.file_uuid;
|
const fileUuid = tokenData.result.file_uuid;
|
||||||
|
uploadData.fields["key"] = fileUuid;
|
||||||
|
delete uploadData.fields["Content-Type"];
|
||||||
|
|
||||||
setStatus('Загрузка файла на сервер...', '');
|
setStatus('Загрузка файла на сервер...', '');
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user