import os from flask import Flask, render_template, request, redirect, url_for, send_from_directory, abort, session, Response, jsonify from werkzeug.utils import secure_filename import mimetypes from flask_httpauth import HTTPBasicAuth from werkzeug.security import generate_password_hash, check_password_hash import shutil app = Flask(__name__) app.secret_key = 'your_secret_key_here' app.config['UPLOAD_FOLDER'] = 'shared_files' app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 * 1024 # 16GB app.config['BASIC_AUTH_USERNAME'] = 'admin' app.config['BASIC_AUTH_PASSWORD'] = 'password' app.config['BASIC_AUTH_FORCE'] = True auth = HTTPBasicAuth() app.jinja_env.globals['os'] = os users = { "admin": generate_password_hash("password"), "user": generate_password_hash("userpass") } @auth.verify_password def verify_password(username, password): if username in users and check_password_hash(users.get(username), password): session['username'] = username return username return None def ensure_upload_folder(): if not os.path.exists(app.config['UPLOAD_FOLDER']): os.makedirs(app.config['UPLOAD_FOLDER']) def get_current_directory(): return session.get('current_directory', '') def set_current_directory(directory): session['current_directory'] = directory @app.route('/get_file_json') @auth.login_required def get_file_json(): directory = request.args.get('dir', '') full_path = os.path.join(app.config['UPLOAD_FOLDER'], directory) if not os.path.isdir(full_path): return jsonify({'error': 'Directory not found'}), 404 files = [] dirs = [] # 指定ディレクトリ内のファイルとサブディレクトリを再帰的に探索 for root, _, filenames in os.walk(full_path): relative_root = os.path.relpath(root, app.config['UPLOAD_FOLDER']) # サブディレクトリ情報を追加 if root != full_path: # 現在のディレクトリ自体は除く dirs.append({ 'name': os.path.basename(root), 'path': relative_root.replace('\\', '/'), # Windows対策 'type': 'directory' }) # ファイル情報を追加 for filename in filenames: file_path = os.path.join(root, filename) relative_path = os.path.join(relative_root, filename).replace('\\', '/') # Windows対策 files.append({ 'name': filename, 'path': relative_path, 'size': os.path.getsize(file_path), 'modified': os.path.getmtime(file_path), 'type': 'file' }) # 親ディレクトリのパスを準備 parent_dir = os.path.dirname(directory) if directory else '' return jsonify({ 'current_dir': directory, 'files': files, 'dirs': dirs, 'parent_dir': parent_dir, 'all_files': files, # すべてのファイルを含む 'all_dirs': dirs # すべてのディレクトリを含む }) def get_full_path(path=''): return os.path.join(app.config['UPLOAD_FOLDER'], get_current_directory(), path) @app.route('/sw.js') def sw(): js_content = render_template('sw.js') return Response(js_content, mimetype='application/javascript') # shared_files ルートを修正 @app.route('/shared_files/') def shared_files(filename): file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) if not os.path.exists(file_path): abort(404) # PDFの場合はインライン表示 if filename.lower().endswith('.pdf'): return send_from_directory( app.config['UPLOAD_FOLDER'], filename, as_attachment=False, mimetype='application/pdf' ) mimetype, _ = mimetypes.guess_type(file_path) if not mimetype: mimetype = 'application/octet-stream' response = send_from_directory( app.config['UPLOAD_FOLDER'], filename, as_attachment=False, mimetype=mimetype ) response.headers.update({ 'X-Content-Type-Options': 'nosniff', 'Cache-Control': 'no-cache, must-revalidate' }) return response @app.route('/') @auth.login_required def index(): ensure_upload_folder() current_dir = get_current_directory() full_path = get_full_path() # ディレクトリが存在しない場合はルートにリセット if not os.path.exists(full_path): set_current_directory('') return redirect(url_for('dev')) files = [] dirs = [] for item in os.listdir(full_path): item_path = os.path.join(full_path, item) if os.path.isfile(item_path): files.append(item) else: dirs.append(item) return render_template('index.html', files=files, dirs=dirs, current_dir=current_dir) @app.route('/api/files') @auth.login_required def get_files_list(): file_list = [] for root, dirs, files in os.walk(app.config['UPLOAD_FOLDER']): for file in files: file_path = os.path.join(root, file) relative_path = os.path.relpath(file_path, app.config['UPLOAD_FOLDER']) file_list.append({ 'path': relative_path, 'size': os.path.getsize(file_path), 'modified': os.path.getmtime(file_path) }) return jsonify(file_list) @app.route('/dev') @auth.login_required def dev(): ensure_upload_folder() current_dir = get_current_directory() full_path = get_full_path() # ディレクトリが存在しない場合はルートにリセット if not os.path.exists(full_path): set_current_directory('') return redirect(url_for('dev')) files = [] dirs = [] try: for item in os.listdir(full_path): item_path = os.path.join(full_path, item) if os.path.isfile(item_path): files.append(item) else: dirs.append(item) except FileNotFoundError: set_current_directory('') return redirect(url_for('dev')) return render_template('dev.html', files=files, dirs=dirs, current_dir=current_dir) @app.route('/change_dir/') @auth.login_required def change_dir(directory): full_path = os.path.join(app.config['UPLOAD_FOLDER'], directory) # ディレクトリが存在する場合のみ変更 if os.path.isdir(full_path): set_current_directory(directory) if request.referrer and 'dev' in request.referrer: return redirect(url_for('dev')) return redirect(url_for('index')) @app.route('/upload', methods=['POST']) @auth.login_required def upload_file(): if 'file' not in request.files: return redirect(request.referrer) file = request.files['file'] if file.filename == '': return redirect(request.referrer) if file: filename = secure_filename(file.filename) # 現在のディレクトリを取得 current_dir = request.form.get('dir', '') # フルパスを構築 upload_path = os.path.join(app.config['UPLOAD_FOLDER'], current_dir) os.makedirs(upload_path, exist_ok=True) full_path = os.path.join(upload_path, filename) file.save(full_path) return redirect(request.referrer) @app.route('/create_folder', methods=['POST']) @auth.login_required def create_folder(): folder_name = request.form.get('folder_name') if folder_name: folder_name = secure_filename(folder_name) full_path = os.path.join(app.config['UPLOAD_FOLDER'], get_current_directory(), folder_name) try: if not os.path.exists(full_path): os.makedirs(full_path, exist_ok=True) # 変更: 作成したフォルダのパスを返す return jsonify({ 'success': True, 'folder_path': os.path.join(get_current_directory(), folder_name) }) else: return jsonify({'success': False, 'error': 'Folder already exists'}), 400 except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 return jsonify({'success': False, 'error': 'No folder name provided'}), 400 @app.route('/delete/') @auth.login_required def delete_file(filename): full_path = get_full_path(filename) if os.path.isfile(full_path): os.remove(full_path) elif os.path.isdir(full_path): shutil.rmtree(full_path) return redirect(request.referrer) @app.route('/rename', methods=['POST']) @auth.login_required def rename_file(): old_name = request.form.get('old_name') new_name = request.form.get('new_name') if old_name and new_name: old_path = get_full_path(old_name) new_path = get_full_path(secure_filename(new_name)) os.rename(old_path, new_path) return redirect(request.referrer) @app.route('/move', methods=['POST']) @auth.login_required def move_file(): filename = request.form.get('filename') destination = request.form.get('destination') if not filename or not destination: return jsonify({'success': False, 'error': 'Missing parameters'}), 400 try: # パスを正規化 src_path = os.path.normpath(os.path.join(app.config['UPLOAD_FOLDER'], filename)) dest_dir = os.path.normpath(os.path.join(app.config['UPLOAD_FOLDER'], destination)) # 移動先ディレクトリが存在しない場合は作成 os.makedirs(dest_dir, exist_ok=True) # 移動先の完全なパス dest_path = os.path.join(dest_dir, os.path.basename(filename)) # 移動実行 shutil.move(src_path, dest_path) # JSONレスポンスではなくリダイレクト return redirect(url_for('dev')) except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 @app.route('/download/') @auth.login_required def download_file(filename): full_path = get_full_path(filename) if not os.path.isfile(full_path): abort(404) return send_from_directory(os.path.dirname(full_path), os.path.basename(full_path), as_attachment=True) @app.route('/files/') def serve_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) if __name__ == '__main__': ensure_upload_folder() app.run(host='0.0.0.0', port=7860)