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)