Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -474,47 +474,61 @@ HTML_CONTENT = """
|
|
474 |
const progressBar = createProgressBar(file.name);
|
475 |
progressContainer.appendChild(progressBar);
|
476 |
|
477 |
-
const
|
478 |
-
|
479 |
-
let uploadedChunks = 0;
|
480 |
|
481 |
-
|
482 |
-
|
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
|
493 |
-
|
494 |
-
|
495 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
496 |
|
497 |
-
|
498 |
-
throw new Error(
|
499 |
-
}
|
500 |
|
501 |
-
const
|
502 |
-
|
503 |
-
uploadedChunks++;
|
504 |
-
updateProgress(progressBar.querySelector('.progress'), (uploadedChunks / totalChunks) * 100);
|
505 |
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
|
|
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
|
518 |
}
|
519 |
}
|
520 |
}
|
@@ -535,8 +549,12 @@ HTML_CONTENT = """
|
|
535 |
return container;
|
536 |
}
|
537 |
|
538 |
-
function updateProgress(progressBar,
|
539 |
-
|
|
|
|
|
|
|
|
|
540 |
}
|
541 |
|
542 |
function resetUploadState() {
|
@@ -609,7 +627,7 @@ async def index():
|
|
609 |
return HTML_CONTENT
|
610 |
|
611 |
@app.post("/upload")
|
612 |
-
async def handle_upload(file: UploadFile = File(...)
|
613 |
if not file.filename:
|
614 |
return JSONResponse(content={"error": "No file selected."}, status_code=400)
|
615 |
|
@@ -617,26 +635,19 @@ async def handle_upload(file: UploadFile = File(...), chunk: int = 0, totalChunk
|
|
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 |
-
|
621 |
-
|
622 |
-
|
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
|
631 |
if not upload_success:
|
632 |
return JSONResponse(content={"error": "File upload failed after multiple attempts"}, status_code=500)
|
633 |
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
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,53 +743,27 @@ async def initiate_upload(cookies: Dict[str, str], filename: str, content_type:
|
|
732 |
print(f'Error initiating upload: {e}')
|
733 |
raise
|
734 |
|
735 |
-
async def
|
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=
|
764 |
-
return response.status_code
|
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,
|
770 |
-
|
|
|
771 |
try:
|
772 |
-
success = await upload_file(upload_url, file_content, content_type
|
773 |
if success:
|
774 |
return True
|
775 |
-
print(f"Upload attempt {
|
776 |
except Exception as e:
|
777 |
-
print(f"Error during upload attempt {
|
778 |
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
|
783 |
-
print("Upload failed after all retry attempts")
|
784 |
return False
|
|
|
474 |
const progressBar = createProgressBar(file.name);
|
475 |
progressContainer.appendChild(progressBar);
|
476 |
|
477 |
+
const formData = new FormData();
|
478 |
+
formData.append('file', file);
|
|
|
479 |
|
480 |
+
let uploadedBytes = 0;
|
481 |
+
let totalBytes = file.size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
482 |
|
483 |
+
while (uploadedBytes < totalBytes) {
|
484 |
try {
|
485 |
+
const xhr = new XMLHttpRequest();
|
486 |
+
xhr.open('POST', '/upload', true);
|
487 |
+
xhr.setRequestHeader('Content-Range', `bytes ${uploadedBytes}-${totalBytes-1}/${totalBytes}`);
|
488 |
+
xhr.upload.onprogress = (event) => updateProgress(event, progressBar.querySelector('.progress'), uploadedBytes);
|
489 |
+
|
490 |
+
xhr.onload = function() {
|
491 |
+
if (xhr.status === 200) {
|
492 |
+
const response = JSON.parse(xhr.responseText);
|
493 |
+
if (response.url) {
|
494 |
+
addResultLink(response.url, file.name);
|
495 |
+
resetUploadState();
|
496 |
+
return;
|
497 |
+
} else {
|
498 |
+
throw new Error('Upload failed: ' + response.error);
|
499 |
+
}
|
500 |
+
} else if (xhr.status === 308) {
|
501 |
+
// Partial upload successful, update uploadedBytes
|
502 |
+
const range = xhr.getResponseHeader('Range');
|
503 |
+
if (range) {
|
504 |
+
uploadedBytes = parseInt(range.split('-')[1]) + 1;
|
505 |
+
}
|
506 |
+
} else {
|
507 |
+
throw new Error(`HTTP error! status: ${xhr.status}`);
|
508 |
+
}
|
509 |
+
};
|
510 |
|
511 |
+
xhr.onerror = function() {
|
512 |
+
throw new Error('Network error occurred');
|
513 |
+
};
|
514 |
|
515 |
+
const chunk = file.slice(uploadedBytes, uploadedBytes + 1024 * 1024); // 1MB chunks
|
516 |
+
xhr.send(chunk);
|
|
|
|
|
517 |
|
518 |
+
// Wait for the request to complete
|
519 |
+
await new Promise((resolve, reject) => {
|
520 |
+
xhr.onloadend = resolve;
|
521 |
+
xhr.onerror = reject;
|
522 |
+
});
|
523 |
+
|
524 |
+
if (uploadedBytes >= totalBytes) {
|
525 |
+
break; // Upload complete
|
526 |
}
|
527 |
} catch (error) {
|
528 |
console.error('Upload error:', error);
|
529 |
+
// Wait for a short time before retrying
|
530 |
await new Promise(resolve => setTimeout(resolve, 1000));
|
531 |
+
// The loop will continue, retrying the upload from where it left off
|
532 |
}
|
533 |
}
|
534 |
}
|
|
|
549 |
return container;
|
550 |
}
|
551 |
|
552 |
+
function updateProgress(event, progressBar, uploadedBytes) {
|
553 |
+
if (event.lengthComputable) {
|
554 |
+
const totalBytes = uploadedBytes + event.total;
|
555 |
+
const percentComplete = ((uploadedBytes + event.loaded) / totalBytes) * 100;
|
556 |
+
progressBar.style.width = percentComplete + '%';
|
557 |
+
}
|
558 |
}
|
559 |
|
560 |
function resetUploadState() {
|
|
|
627 |
return HTML_CONTENT
|
628 |
|
629 |
@app.post("/upload")
|
630 |
+
async def handle_upload(file: UploadFile = File(...)):
|
631 |
if not file.filename:
|
632 |
return JSONResponse(content={"error": "No file selected."}, status_code=400)
|
633 |
|
|
|
635 |
if 'csrftoken' not in cookies or 'sessionid' not in cookies:
|
636 |
return JSONResponse(content={"error": "Failed to obtain necessary cookies"}, status_code=500)
|
637 |
|
638 |
+
upload_result = await initiate_upload(cookies, file.filename, file.content_type)
|
639 |
+
if not upload_result or 'upload_url' not in upload_result:
|
640 |
+
return JSONResponse(content={"error": "Failed to initiate upload"}, status_code=500)
|
|
|
|
|
|
|
|
|
|
|
641 |
|
642 |
file_content = await file.read()
|
643 |
+
upload_success = await retry_upload(upload_result['upload_url'], file_content, file.content_type)
|
644 |
if not upload_success:
|
645 |
return JSONResponse(content={"error": "File upload failed after multiple attempts"}, status_code=500)
|
646 |
|
647 |
+
original_url = upload_result['serving_url']
|
648 |
+
mirrored_url = f"/rbxg/{original_url.split('/pbxt/')[1]}"
|
649 |
+
|
650 |
+
return JSONResponse(content={"url": mirrored_url})
|
|
|
|
|
651 |
|
652 |
@app.get("/rbxg/{path:path}")
|
653 |
async def handle_video_stream(path: str, request: Request):
|
|
|
743 |
print(f'Error initiating upload: {e}')
|
744 |
raise
|
745 |
|
746 |
+
async def upload_file(upload_url: str, file_content: bytes, content_type: str) -> bool:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
747 |
try:
|
748 |
+
response = requests.put(upload_url, data=file_content, headers={'Content-Type': content_type})
|
749 |
+
return response.status_code == 200
|
750 |
except Exception as e:
|
751 |
print(f'Error uploading file: {e}')
|
752 |
return False
|
753 |
|
754 |
+
async def retry_upload(upload_url: str, file_content: bytes, content_type: str, max_retries: int = 5, delay: int = 1) -> bool:
|
755 |
+
retries = 0
|
756 |
+
while retries < max_retries:
|
757 |
try:
|
758 |
+
success = await upload_file(upload_url, file_content, content_type)
|
759 |
if success:
|
760 |
return True
|
761 |
+
print(f"Upload attempt {retries + 1} failed. Retrying...")
|
762 |
except Exception as e:
|
763 |
+
print(f"Error during upload attempt {retries + 1}: {e}")
|
764 |
|
765 |
+
retries += 1
|
766 |
+
await asyncio.sleep(delay)
|
767 |
+
delay = min(delay * 2, 60) # Exponential backoff, capped at 60 seconds
|
768 |
|
|
|
769 |
return False
|