document upload/download/delete ok
This commit is contained in:
parent
9f93aa854b
commit
417b2b4470
1
.gitignore
vendored
1
.gitignore
vendored
@ -10,3 +10,4 @@ $*
|
||||
venv/
|
||||
__pycache__/
|
||||
.vscode/
|
||||
file_storage/
|
||||
@ -13,8 +13,10 @@ def create_app(test_config=None):
|
||||
DATABASE_USER='root',
|
||||
DATABASE_HOST='localhost',
|
||||
DATABASE_PASS='lil0,.lil0',
|
||||
UPLOADDIR=os.path.join("./file_storage"),
|
||||
)
|
||||
|
||||
if not os.path.exists(app.config['UPLOADDIR']):
|
||||
os.mkdir(app.config['UPLOADDIR'])
|
||||
if test_config is None:
|
||||
app.config.from_pyfile('config.py', silent=True)
|
||||
else:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block header %}
|
||||
<style>
|
||||
<style>
|
||||
.maindiv {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -12,16 +12,17 @@
|
||||
padding-left: 1.2rem;
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
.sidenav {
|
||||
height: 100%;
|
||||
max-width: 160px;
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="container">
|
||||
<div class="columns">
|
||||
<div class="column col-3">
|
||||
<ul class="nav">
|
||||
@ -70,27 +71,47 @@
|
||||
<mark>语言:</mark><span class="px-2">{{book['book_lang']}}</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div>
|
||||
<div class="columns">
|
||||
<div class="column col-2">
|
||||
<a href="/book/update/{{book['book_id']}}/" class="btn btn-primary">编辑图书信息</a>
|
||||
</div>
|
||||
<div class="divider-vert"></div>
|
||||
<div class="column col-6">
|
||||
<form method="post" class="form-group p-centered" action="/doc/upload/{{book['book_id']}}/"
|
||||
enctype="multipart/form-data">
|
||||
<input class="form-input form-inline col-9" type="file" name="file" required>
|
||||
<input class="btn btn-primary input-group-btn form-inline" type="submit" value="上传">
|
||||
</form>
|
||||
</div>
|
||||
<div class="divider-vert"></div>
|
||||
<div class="column">
|
||||
<a href="" class="btn btn-primary">加一个评论</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="book-docs" class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">文档1</div>
|
||||
<div class="card-subtitle">
|
||||
<span>大小:</span>
|
||||
<span>日期:</span>
|
||||
<div class="float-right">
|
||||
<button class="btn btn-primary">下载</button>
|
||||
<button class="btn">删除</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="divider"></div>
|
||||
<div id = "book-notes" class="card">
|
||||
<div class="divider text-center" data-content="文档"></div>
|
||||
|
||||
{% for document in documents %}
|
||||
<div id="doc{{document['doc_id']}}" class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title h5">{{document['doc_name']}}</div>
|
||||
<div class="card-subtitle">
|
||||
<span><mark>大小</mark> {{document['doc_size']}} KB</span>
|
||||
<span><mark>日期</mark>{{document['doc_date']}}</span>
|
||||
<div class="float-right">
|
||||
<a href="/doc/download/{{document['doc_id']}}/" class="btn btn-primary">下载</a>
|
||||
<a href="/doc/delete/{{document['doc_id']}}/" class="btn">删除</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="divider text-center" data-content="评论"></div>
|
||||
<div id="book-notes" class="card">
|
||||
<div class="card-header">
|
||||
space
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
@ -98,5 +119,5 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -45,7 +45,11 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p>{{opresult}}</p>
|
||||
{% if ret_url %}
|
||||
<p><a href="{{ret_url}}">返回</a></p>
|
||||
{% else %}
|
||||
<p><a href="javascript:history.back(-1)">返回</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
Rendered @ {{cur_time}}
|
||||
|
||||
102
src/user.py
102
src/user.py
@ -1,10 +1,8 @@
|
||||
from flask import (
|
||||
Blueprint, flash, g, redirect, render_template, request, url_for
|
||||
Blueprint, flash, g, redirect, render_template, request, url_for, send_file, current_app,
|
||||
)
|
||||
import re
|
||||
from werkzeug.exceptions import abort
|
||||
from werkzeug.security import generate_password_hash
|
||||
|
||||
import os
|
||||
from src.auth import login_required
|
||||
from src.db import get_db
|
||||
import pymysql
|
||||
@ -211,8 +209,10 @@ def book(id):
|
||||
book = cur.fetchone()
|
||||
cur.execute("select * from v_book_to_types where book_id=%s", (book['book_id'], ))
|
||||
booktype = cur.fetchall()
|
||||
cur.execute("select * from document where book_id=%s", (book['book_id'], ))
|
||||
documents = cur.fetchall()
|
||||
return render_template("/user/book.html",
|
||||
book=book, booktype=booktype,
|
||||
book=book, booktype=booktype, documents=documents,
|
||||
cur_time=datetime.datetime.now())
|
||||
|
||||
@bp.route("/book/update/<int:id>/", methods=("GET", "POST"))
|
||||
@ -293,3 +293,95 @@ def book_update(id):
|
||||
return render_template("/user/updatebook.html",
|
||||
book=bookinfo, booktype=booktypestr, typelist=typelist,
|
||||
cur_time=datetime.datetime.now())
|
||||
|
||||
|
||||
@bp.route("/doc/upload/<int:id>/", methods=("POST",))
|
||||
@login_required
|
||||
def doc_upload(id):
|
||||
db = get_db()
|
||||
cur = db.cursor()
|
||||
assert(request.method=="POST")
|
||||
fileobj = request.files['file']
|
||||
error = None
|
||||
if fileobj and fileobj.filename:
|
||||
_, filename = os.path.split(fileobj.filename)
|
||||
filepath = os.path.join(current_app.config['UPLOADDIR'], filename + f'.{int(datetime.datetime.timestamp(datetime.datetime.now()))}')
|
||||
fileobj.save(filepath)
|
||||
filesz = os.stat(filepath).st_size // 1024 # original in bytes
|
||||
filetype = fileobj.mimetype
|
||||
print(filetype)
|
||||
print(filesz)
|
||||
try:
|
||||
cur.execute(
|
||||
"insert into document (`doc_name`,`doc_url`,`doc_size`,`doc_type`,`book_id`,`user_id`)"
|
||||
"values (%s,%s,%s,%s,%s,%s)",
|
||||
(filename, filepath, filesz, filetype, id, g.user['user_id'])
|
||||
)
|
||||
db.commit()
|
||||
except pymysql.Error as _e:
|
||||
error = "未知错误 %s" % (_e)
|
||||
db.rollback()
|
||||
else:
|
||||
error = "未收到有效的文件"
|
||||
cur.close()
|
||||
if error is not None:
|
||||
return render_template("/user/result.html",
|
||||
opname="上传文件失败", opresult=error,
|
||||
cur_time=datetime.datetime.now())
|
||||
return redirect(url_for("user.book", id=id))
|
||||
|
||||
@bp.route("/doc/download/<int:docid>/", methods=("GET",))
|
||||
@login_required
|
||||
def doc_download(docid):
|
||||
db = get_db()
|
||||
cur = db.cursor()
|
||||
error = None
|
||||
cur.execute("select * from document where doc_id=%s", (docid,))
|
||||
document = cur.fetchone()
|
||||
|
||||
if document is None:
|
||||
error = "文件不存在"
|
||||
else:
|
||||
docpath = os.path.join(os.getcwd(),document['doc_url'])
|
||||
if os.path.exists(docpath):
|
||||
return send_file(docpath, download_name=document['doc_name'], mimetype=document['doc_type'])
|
||||
else:
|
||||
error = "文件已被删除,严重的数据不一致,请联系管理员"
|
||||
return render_template("/user/result.html",
|
||||
opname="下载文件失败", opresult=error,
|
||||
cur_time=datetime.datetime.now())
|
||||
|
||||
@bp.route("/doc/delete/<int:docid>/", methods=("GET",))
|
||||
@login_required
|
||||
def doc_delete(docid):
|
||||
db = get_db()
|
||||
cur = db.cursor()
|
||||
error = None
|
||||
warning = None
|
||||
cur.execute("select * from document where doc_id=%s", (docid,))
|
||||
document = cur.fetchone()
|
||||
|
||||
if document is None:
|
||||
error = "文件不存在"
|
||||
else:
|
||||
docpath = os.path.join(os.getcwd(),document['doc_url'])
|
||||
if os.path.exists(docpath):
|
||||
os.remove(docpath)
|
||||
else:
|
||||
warning = "文件已经删除,但是数据库记录仍存在"
|
||||
if error is None:
|
||||
try:
|
||||
cur.execute("delete from document where `doc_id`=%s", (docid))
|
||||
db.commit()
|
||||
except pymysql.Error as _e:
|
||||
error = "严重错误:%s。\n请联系管理员解决问题" % (_e)
|
||||
cur.close()
|
||||
if error is not None:
|
||||
return render_template("/user/result.html",
|
||||
opname="删除文件失败", opresult=error,
|
||||
cur_time=datetime.datetime.now())
|
||||
elif warning is not None:
|
||||
return render_template("/user/result.html",
|
||||
opname="删除文件出现了一些意外", opresult=warning,
|
||||
cur_time=datetime.datetime.now(), ret_url=url_for("user.book", id=document['book_id']))
|
||||
return redirect(url_for("user.book", id=document['book_id']))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user