Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -474,48 +474,47 @@ HTML_CONTENT = """
|
|
474 |
const progressBar = createProgressBar(file.name);
|
475 |
progressContainer.appendChild(progressBar);
|
476 |
|
477 |
-
const
|
478 |
-
|
|
|
479 |
|
480 |
-
while (
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
xhr.upload.onprogress = (event) => updateProgress(event, progressBar.querySelector('.progress'));
|
485 |
-
|
486 |
-
xhr.onload = function() {
|
487 |
-
if (xhr.status === 200) {
|
488 |
-
const response = JSON.parse(xhr.responseText);
|
489 |
-
if (response.url) {
|
490 |
-
addResultLink(response.url, file.name);
|
491 |
-
resetUploadState();
|
492 |
-
return;
|
493 |
-
} else {
|
494 |
-
throw new Error('Upload failed: ' + response.error);
|
495 |
-
}
|
496 |
-
} else {
|
497 |
-
throw new Error(`HTTP error! status: ${xhr.status}`);
|
498 |
-
}
|
499 |
-
};
|
500 |
|
501 |
-
|
502 |
-
|
503 |
-
|
|
|
504 |
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
xhr.onloadend = resolve;
|
510 |
-
xhr.onerror = reject;
|
511 |
});
|
512 |
|
513 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
514 |
} catch (error) {
|
515 |
console.error('Upload error:', error);
|
516 |
-
// Wait for a short time before retrying
|
517 |
await new Promise(resolve => setTimeout(resolve, 1000));
|
518 |
-
// The loop will continue, retrying the
|
519 |
}
|
520 |
}
|
521 |
}
|
@@ -536,11 +535,8 @@ HTML_CONTENT = """
|
|
536 |
return container;
|
537 |
}
|
538 |
|
539 |
-
function updateProgress(
|
540 |
-
|
541 |
-
const percentComplete = (event.loaded / event.total) * 100;
|
542 |
-
progressBar.style.width = percentComplete + '%';
|
543 |
-
}
|
544 |
}
|
545 |
|
546 |
function resetUploadState() {
|
@@ -613,7 +609,7 @@ async def index():
|
|
613 |
return HTML_CONTENT
|
614 |
|
615 |
@app.post("/upload")
|
616 |
-
async def handle_upload(file: UploadFile = File(...)):
|
617 |
if not file.filename:
|
618 |
return JSONResponse(content={"error": "No file selected."}, status_code=400)
|
619 |
|
@@ -621,19 +617,26 @@ async def handle_upload(file: UploadFile = File(...)):
|
|
621 |
if 'csrftoken' not in cookies or 'sessionid' not in cookies:
|
622 |
return JSONResponse(content={"error": "Failed to obtain necessary cookies"}, status_code=500)
|
623 |
|
624 |
-
|
625 |
-
|
626 |
-
|
|
|
|
|
|
|
|
|
|
|
627 |
|
628 |
file_content = await file.read()
|
629 |
-
upload_success = await retry_upload(upload_result['upload_url'], file_content, file.content_type)
|
630 |
if not upload_success:
|
631 |
return JSONResponse(content={"error": "File upload failed after multiple attempts"}, status_code=500)
|
632 |
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
|
|
|
|
637 |
|
638 |
@app.get("/rbxg/{path:path}")
|
639 |
async def handle_video_stream(path: str, request: Request):
|
@@ -729,25 +732,53 @@ async def initiate_upload(cookies: Dict[str, str], filename: str, content_type:
|
|
729 |
print(f'Error initiating upload: {e}')
|
730 |
raise
|
731 |
|
732 |
-
async def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
733 |
try:
|
734 |
-
response = requests.put(upload_url, data=file_content, headers=
|
735 |
-
return response.status_code
|
736 |
except Exception as e:
|
737 |
print(f'Error uploading file: {e}')
|
738 |
return False
|
739 |
|
740 |
-
async def retry_upload(upload_url: str, file_content: bytes, content_type: str, max_retries: int = 5, delay: int = 1) -> bool:
|
741 |
-
|
742 |
try:
|
743 |
-
success = await upload_file(upload_url, file_content, content_type)
|
744 |
if success:
|
745 |
return True
|
746 |
-
print("Upload failed. Retrying...")
|
747 |
except Exception as e:
|
748 |
-
print(f"Error during upload: {e}")
|
749 |
|
750 |
-
|
751 |
-
|
|
|
752 |
|
|
|
753 |
return False
|
|
|
474 |
const progressBar = createProgressBar(file.name);
|
475 |
progressContainer.appendChild(progressBar);
|
476 |
|
477 |
+
const chunkSize = 1024 * 1024; // 1MB chunks
|
478 |
+
const totalChunks = Math.ceil(file.size / chunkSize);
|
479 |
+
let uploadedChunks = 0;
|
480 |
|
481 |
+
while (uploadedChunks < totalChunks) {
|
482 |
+
const start = uploadedChunks * chunkSize;
|
483 |
+
const end = Math.min(start + chunkSize, file.size);
|
484 |
+
const chunk = file.slice(start, end);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
485 |
|
486 |
+
const formData = new FormData();
|
487 |
+
formData.append('file', chunk, file.name);
|
488 |
+
formData.append('chunk', uploadedChunks.toString());
|
489 |
+
formData.append('totalChunks', totalChunks.toString());
|
490 |
|
491 |
+
try {
|
492 |
+
const response = await fetch('/upload', {
|
493 |
+
method: 'POST',
|
494 |
+
body: formData
|
|
|
|
|
495 |
});
|
496 |
|
497 |
+
if (!response.ok) {
|
498 |
+
throw new Error(`HTTP error! status: ${response.status}`);
|
499 |
+
}
|
500 |
+
|
501 |
+
const result = await response.json();
|
502 |
+
if (result.success) {
|
503 |
+
uploadedChunks++;
|
504 |
+
updateProgress(progressBar.querySelector('.progress'), (uploadedChunks / totalChunks) * 100);
|
505 |
+
|
506 |
+
if (uploadedChunks === totalChunks) {
|
507 |
+
addResultLink(result.url, file.name);
|
508 |
+
resetUploadState();
|
509 |
+
break;
|
510 |
+
}
|
511 |
+
} else {
|
512 |
+
throw new Error(result.error || 'Upload failed');
|
513 |
+
}
|
514 |
} catch (error) {
|
515 |
console.error('Upload error:', error);
|
|
|
516 |
await new Promise(resolve => setTimeout(resolve, 1000));
|
517 |
+
// The loop will continue, retrying the current chunk
|
518 |
}
|
519 |
}
|
520 |
}
|
|
|
535 |
return container;
|
536 |
}
|
537 |
|
538 |
+
function updateProgress(progressBar, percentage) {
|
539 |
+
progressBar.style.width = percentage + '%';
|
|
|
|
|
|
|
540 |
}
|
541 |
|
542 |
function resetUploadState() {
|
|
|
609 |
return HTML_CONTENT
|
610 |
|
611 |
@app.post("/upload")
|
612 |
+
async def handle_upload(file: UploadFile = File(...), chunk: int = 0, totalChunks: int = 1):
|
613 |
if not file.filename:
|
614 |
return JSONResponse(content={"error": "No file selected."}, status_code=400)
|
615 |
|
|
|
617 |
if 'csrftoken' not in cookies or 'sessionid' not in cookies:
|
618 |
return JSONResponse(content={"error": "Failed to obtain necessary cookies"}, status_code=500)
|
619 |
|
620 |
+
if chunk == 0:
|
621 |
+
upload_result = await initiate_upload(cookies, file.filename, file.content_type)
|
622 |
+
if not upload_result or 'upload_url' not in upload_result:
|
623 |
+
return JSONResponse(content={"error": "Failed to initiate upload"}, status_code=500)
|
624 |
+
else:
|
625 |
+
upload_result = await get_upload_status(cookies, file.filename)
|
626 |
+
if not upload_result or 'upload_url' not in upload_result:
|
627 |
+
return JSONResponse(content={"error": "Failed to get upload status"}, status_code=500)
|
628 |
|
629 |
file_content = await file.read()
|
630 |
+
upload_success = await retry_upload(upload_result['upload_url'], file_content, file.content_type, chunk, totalChunks)
|
631 |
if not upload_success:
|
632 |
return JSONResponse(content={"error": "File upload failed after multiple attempts"}, status_code=500)
|
633 |
|
634 |
+
if chunk == totalChunks - 1:
|
635 |
+
original_url = upload_result['serving_url']
|
636 |
+
mirrored_url = f"/rbxg/{original_url.split('/pbxt/')[1]}"
|
637 |
+
return JSONResponse(content={"success": True, "url": mirrored_url})
|
638 |
+
else:
|
639 |
+
return JSONResponse(content={"success": True})
|
640 |
|
641 |
@app.get("/rbxg/{path:path}")
|
642 |
async def handle_video_stream(path: str, request: Request):
|
|
|
732 |
print(f'Error initiating upload: {e}')
|
733 |
raise
|
734 |
|
735 |
+
async def get_upload_status(cookies: Dict[str, str], filename: str) -> Dict:
|
736 |
+
url = f'https://replicate.com/api/upload/{filename}'
|
737 |
+
try:
|
738 |
+
response = requests.get(url, cookies=cookies, headers={
|
739 |
+
'X-CSRFToken': cookies.get('csrftoken'),
|
740 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
|
741 |
+
'Referer': 'https://replicate.com/levelsio/neon-tokyo',
|
742 |
+
'Origin': 'https://replicate.com',
|
743 |
+
'Accept': '*/*',
|
744 |
+
'Accept-Language': 'en-US,en;q=0.5',
|
745 |
+
'Accept-Encoding': 'identity',
|
746 |
+
'Sec-Fetch-Dest': 'empty',
|
747 |
+
'Sec-Fetch-Mode': 'cors',
|
748 |
+
'Sec-Fetch-Site': 'same-origin',
|
749 |
+
'Sec-GPC': '1',
|
750 |
+
'Priority': 'u=1, i'
|
751 |
+
})
|
752 |
+
return response.json()
|
753 |
+
except Exception as e:
|
754 |
+
print(f'Error getting upload status: {e}')
|
755 |
+
raise
|
756 |
+
|
757 |
+
async def upload_file(upload_url: str, file_content: bytes, content_type: str, chunk: int, totalChunks: int) -> bool:
|
758 |
+
headers = {
|
759 |
+
'Content-Type': content_type,
|
760 |
+
'Content-Range': f'bytes {chunk*len(file_content)}-{(chunk+1)*len(file_content)-1}/{totalChunks*len(file_content)}'
|
761 |
+
}
|
762 |
try:
|
763 |
+
response = requests.put(upload_url, data=file_content, headers=headers)
|
764 |
+
return response.status_code in [200, 201, 204]
|
765 |
except Exception as e:
|
766 |
print(f'Error uploading file: {e}')
|
767 |
return False
|
768 |
|
769 |
+
async def retry_upload(upload_url: str, file_content: bytes, content_type: str, chunk: int, totalChunks: int, max_retries: int = 5, delay: int = 1) -> bool:
|
770 |
+
for attempt in range(max_retries):
|
771 |
try:
|
772 |
+
success = await upload_file(upload_url, file_content, content_type, chunk, totalChunks)
|
773 |
if success:
|
774 |
return True
|
775 |
+
print(f"Upload attempt {attempt + 1} failed. Retrying...")
|
776 |
except Exception as e:
|
777 |
+
print(f"Error during upload attempt {attempt + 1}: {e}")
|
778 |
|
779 |
+
if attempt < max_retries - 1:
|
780 |
+
await asyncio.sleep(delay)
|
781 |
+
delay *= 2 # Exponential backoff
|
782 |
|
783 |
+
print("Upload failed after all retry attempts")
|
784 |
return False
|