Upload File dari Cloudflare R2 ke AWS S3 Pakai Python Parallel

Upload File dari Cloudflare R2 ke AWS S3 Pakai Python Parallel

Catatan praktis bikin script Python untuk download dari Cloudflare R2 lalu upload ke AWS S3, sambil hapus URL yang sukses dari list.

Masalahnya gini

Gue punya list file MP4 yang disimpan di Cloudflare R2, isinya ada di listmp4.txt. Targetnya, file-file itu mau dipindahin ke AWS S3. Jadi alurnya simpel: download dari R2, upload ke S3, lalu URL yang sukses dihapus dari list biar next run tinggal lanjut sisanya.

Kalau dikerjain manual, jelas capek. Apalagi kalau file-nya banyak. Jadi yang paling enak ya bikin script yang jalan otomatis, bisa parallel, dan aman buat diulang kalau ada yang gagal.

Solusi yang gue pakai

Gue bikin script Python yang:

  • ambil URL dari listmp4.txt
  • download file dari R2 pakai streaming
  • langsung upload ke S3 tanpa simpan file full di disk
  • jalan parallel biar lebih cepat
  • hapus URL yang sukses dari list

Ini enak karena hemat RAM, nggak bikin storage lokal penuh, dan kalau gagal tinggal rerun aja.

Install dependency

pip install boto3 requests

Script Python

Ganti dulu credential AWS dan sesuaikan bucket, folder, serta endpoint kalau perlu.

import os
import sys
import time
import boto3
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.parse import urlparse

# ================== CONFIG ==================
AWS_ACCESS_KEY = 'MASUKKAN_ACCESS_KEY_KAMU'
AWS_SECRET_KEY = 'MASUKKAN_SECRET_KEY_KAMU'

BUCKET_NAME = 'dramaku'
S3_FOLDER = 'dramabox/'
LIST_FILE = 'listmp4.txt'
MAX_WORKERS = 5          # Bisa dinaikkan jadi 8-10 kalau stabil
TIMEOUT = 300            # 5 menit
# ===========================================

s3_client = boto3.client(
    's3',
    aws_access_key_id=AWS_ACCESS_KEY,
    aws_secret_access_key=AWS_SECRET_KEY,
    endpoint_url='https://s3.dualstack.us-east-1.amazonaws.com'
)

def get_filename_from_url(url):
    return os.path.basename(urlparse(url).path)

def download_and_upload(url):
    filename = get_filename_from_url(url)
    try:
        s3_key = S3_FOLDER + filename
        print(f'[{filename}] Download dan upload mulai...')

        with requests.get(url, stream=True, timeout=TIMEOUT) as r:
            r.raise_for_status()
            s3_client.upload_fileobj(
                r.raw,
                BUCKET_NAME,
                s3_key,
                ExtraArgs={'ContentType': 'video/mp4'}
            )

        print(f'BERHASIL: {filename}')
        return url, True

    except Exception as e:
        print(f'GAGAL: {filename} | {str(e)}')
        return url, False

def main():
    if not os.path.exists(LIST_FILE):
        print(f'File {LIST_FILE} tidak ditemukan!')
        sys.exit(1)

    with open(LIST_FILE, 'r') as f:
        urls = [line.strip() for line in f if line.strip() and not line.startswith('#')]

    if not urls:
        print('List kosong, tidak ada yang perlu diupload.')
        return

    print(f'Mulai proses {len(urls)} file dengan {MAX_WORKERS} worker...')

    successful = []
    start_time = time.time()

    with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
        future_to_url = {executor.submit(download_and_upload, url): url for url in urls}

        for future in as_completed(future_to_url):
            url, success = future.result()
            if success:
                successful.append(url)

    if successful:
        remaining = [u for u in urls if u not in successful]
        with open(LIST_FILE, 'w') as f:
            for u in remaining:
                f.write(u + '\n')

        print('SELESAI')
        print(f'Berhasil: {len(successful)} file')
        print(f'Sisa di list: {len(remaining)} file')
    else:
        print('Tidak ada file yang berhasil diupload.')

    elapsed = time.time() - start_time
    print(f'Total waktu: {elapsed/60:.1f} menit')

if __name__ == '__main__':
    main()

Cara pakai

  1. Simpan script misalnya dengan nama download_and_upload_parallel.py
  2. Isi credential AWS di bagian config
  3. Pastikan listmp4.txt ada di folder yang sama
  4. Jalankan script
python3 download_and_upload_parallel.py

Catatan penting

  • Kalau file besar dan koneksi stabil, MAX_WORKERS bisa dinaikkan ke 8 atau 10.
  • Kalau sering gagal, turunin worker biar lebih aman.
  • Script ini cocok buat file yang memang mau dipindah bertahap, bukan sekali jalan terus lupa.
  • Karena yang sukses langsung dihapus dari list, rerun script jadi gampang.

Kalau mau lebih praktis

Kalau file-nya sebenarnya sudah bisa diakses publik dan cuma mau dipindah antar storage, script model begini sudah cukup praktis. Tapi kalau workflow-nya sering dipakai, ada beberapa upgrade yang bisa bikin hidup lebih enak:

  • tambahin retry otomatis kalau upload gagal
  • log hasil ke file biar gampang audit
  • cek dulu apakah object sudah ada di S3 sebelum upload
  • pakai progress bar kalau jumlah file banyak

Kalau gue pribadi, versi parallel + hapus URL sukses dari list itu udah paling balance: simpel, cepat, dan gampang diulang.

Masalah yang mungkin muncul

1. Credential AWS salah
Biasanya upload langsung gagal. Cek lagi access key dan secret key-nya.

2. Endpoint S3 keliru
Pastikan endpoint yang dipakai sesuai bucket dan region tujuan.

3. File gagal di tengah jalan
Turunin jumlah worker atau tambah retry biar lebih tahan banting.

4. List tidak berkurang
Pastikan script memang menulis ulang listmp4.txt setelah proses selesai.

Penutup

Intinya, kalau lu punya banyak URL file di R2 dan mau dipindah ke S3, jangan dikerjain manual. Bikin script yang streaming, parallel, dan bisa lanjut dari sisa list. Jauh lebih waras, bro.

Kalau mau, next step bisa gue bantu bikinin versi yang ada retry, progress bar, atau cek file duplikat sebelum upload.

Tags: Catatan Teknis, Python, AWS S3, Cloudflare R2, upload file