4cko
/usr/local/rvm/gems/ruby-3.4.7/bin:/usr/local/rvm/gems/ruby-3.4.7@global/bin:/usr/local/rvm/rubies/ruby-3.4.7/bin:/home/codespace/.vscode-remote/data/User/globalStorage/github.copilot-chat/debugCommand:/home/codespace/.vscode-remote/data/User/globalStorage/github.copilot-chat/copilotCli:/vscode/bin/linux-x64/7e7950df89d055b5a378379db9ee14290772148a/bin/remote-cli:/home/codespace/.local/bin:/home/codespace/.dotnet:/home/codespace/nvm/current/bin:/home/codespace/.php/current/bin:/home/codespace/.python/current/bin:/home/codespace/java/current/bin:/home/codespace/.ruby/current/bin:/home/codespace/.local/bin:/usr/local/python/current/bin:/usr/local/py-utils/bin:/usr/local/jupyter:/usr/local/oryx:/usr/local/go/bin:/go/bin:/usr/local/sdkman/bin:/usr/local/sdkman/candidates/java/current/bin:/usr/local/sdkman/candidates/gradle/current/bin:/usr/local/sdkman/candidates/maven/current/bin:/usr/local/sdkman/candidates/ant/current/bin:/usr/local/rvm/gems/default/bin:/usr/local/rvm/gems/default@global/bin:/usr/local/rvm/rubies/default/bin:/usr/local/share/rbenv/bin:/usr/local/php/current/bin:/opt/conda/bin:/usr/local/nvs:/usr/local/share/nvm/versions/node/v24.14.0/bin:/usr/local/hugo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/share/dotnet:/home/codespace/.dotnet/tools:/usr/local/rvm/bin
a25386c | from flask import Flask, request, jsonify | |
| from werkzeug.utils import secure_filename | |
| import os | |
| from datetime import datetime | |
| import logging | |
| from dotenv import load_dotenv | |
| from hf_uploader import upload_file, upload_folder | |
| import tempfile | |
| import shutil | |
| # Load environment variables | |
| load_dotenv() | |
| # Setup Flask app | |
| app = Flask(__name__) | |
| app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 * 1024 # 100MB max file size | |
| app.config['UPLOAD_FOLDER'] = 'uploads' | |
| # Setup logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| # Create uploads folder if not exists | |
| if not os.path.exists(app.config['UPLOAD_FOLDER']): | |
| os.makedirs(app.config['UPLOAD_FOLDER']) | |
| # Allowed file extensions (optional, allow all) | |
| ALLOWED_EXTENSIONS = set(['*']) | |
| def allowed_file(filename): | |
| return True # Allow all files | |
| def health_check(): | |
| """Health check endpoint""" | |
| return jsonify({ | |
| 'status': 'ok', | |
| 'message': 'Hugging Face File Upload API', | |
| 'version': '1.0.0', | |
| 'language': 'Python', | |
| 'framework': 'Flask', | |
| 'endpoints': { | |
| 'upload': { | |
| 'method': 'POST', | |
| 'path': '/api/upload', | |
| 'description': 'Upload file ke Hugging Face dataset', | |
| 'required': ['file', 'repo_id', 'token'], | |
| 'optional': ['subfolder'] | |
| } | |
| } | |
| }) | |
| def upload(): | |
| """Upload file to Hugging Face""" | |
| try: | |
| # Validasi file | |
| if 'file' not in request.files: | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'File tidak ditemukan' | |
| }), 400 | |
| file = request.files['file'] | |
| if file.filename == '': | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'File tidak dipilih' | |
| }), 400 | |
| if not allowed_file(file.filename): | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'File type tidak diizinkan' | |
| }), 400 | |
| # Get form data | |
| repo_id = request.form.get('repo_id') or os.getenv('HF_REPO_ID') | |
| token = request.form.get('token') or os.getenv('HF_TOKEN') | |
| subfolder = request.form.get('subfolder', '') | |
| # Validate required fields | |
| if not repo_id or not token: | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'repo_id dan token diperlukan (kirim via request atau set di .env)', | |
| 'required_fields': ['repo_id', 'token'], | |
| 'hint': 'Set HF_REPO_ID dan HF_TOKEN di .env atau kirim via form data' | |
| }), 400 | |
| # Save file temporarily | |
| filename = secure_filename(file.filename) | |
| temp_dir = tempfile.mkdtemp() | |
| file_path = os.path.join(temp_dir, filename) | |
| file.save(file_path) | |
| file_size = os.path.getsize(file_path) | |
| logger.info(f'Uploading {filename} ({file_size} bytes) to {repo_id}') | |
| try: | |
| # Upload to Hugging Face | |
| result = upload_file( | |
| file_path=file_path, | |
| file_name=filename, | |
| repo_id=repo_id, | |
| token=token, | |
| subfolder=subfolder | |
| ) | |
| # Cleanup | |
| shutil.rmtree(temp_dir) | |
| return jsonify({ | |
| 'success': True, | |
| 'message': 'File berhasil di-upload ke Hugging Face', | |
| 'data': { | |
| 'file_name': filename, | |
| 'file_size': file_size, | |
| 'repo_id': repo_id, | |
| 'path_prefix': '/u/', | |
| 'subfolder': subfolder or 'root', | |
| 'url': result['url'], | |
| 'file_path': result['file_path'], | |
| 'upload_timestamp': datetime.utcnow().isoformat() + 'Z' | |
| } | |
| }), 200 | |
| except Exception as upload_error: | |
| # Cleanup on error | |
| shutil.rmtree(temp_dir) | |
| logger.error(f'Upload error: {str(upload_error)}') | |
| error_msg = str(upload_error) | |
| if 'Token' in error_msg or 'Unauthorized' in error_msg: | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'Token tidak valid atau expired' | |
| }), 401 | |
| elif 'Repository' in error_msg or 'Not found' in error_msg: | |
| return jsonify({ | |
| 'success': False, | |
| 'error': f'Repository tidak ditemukan: {repo_id}' | |
| }), 404 | |
| else: | |
| return jsonify({ | |
| 'success': False, | |
| 'error': error_msg | |
| }), 500 | |
| except Exception as error: | |
| logger.error(f'Error: {str(error)}') | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'Internal Server Error', | |
| 'message': str(error) | |
| }), 500 | |
| def not_found(error): | |
| """404 handler""" | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'Endpoint tidak ditemukan' | |
| }), 404 | |
| def server_error(error): | |
| """500 handler""" | |
| return jsonify({ | |
| 'success': False, | |
| 'error': 'Internal Server Error' | |
| }), 500 | |
| if __name__ == '__main__': | |
| port = int(os.getenv('PORT', 3000)) | |
| debug = os.getenv('NODE_ENV', 'development') == 'development' | |
| logger.info(f'🚀 API server berjalan di http://localhost:{port}') | |
| logger.info(f'📤 Endpoint upload: POST http://localhost:{port}/api/upload') | |
| app.run(host='0.0.0.0', port=port, debug=debug) | |