File size: 5,714 Bytes
a25386c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | 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)
|