ge / server.py
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
Raw
History Blame Contribute Delete
5.71 kB
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
@app.route('/', methods=['GET'])
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']
}
}
})
@app.route('/api/upload', methods=['POST'])
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
@app.errorhandler(404)
def not_found(error):
"""404 handler"""
return jsonify({
'success': False,
'error': 'Endpoint tidak ditemukan'
}), 404
@app.errorhandler(500)
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)