soiz1's picture
Update app.py
e9ecab4 verified
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/<path:filename>')
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/<path:directory>')
@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/<path:filename>')
@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/<path:filename>')
@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/<path:filename>')
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)