Browse Source

feat: download zip

master
欧醚 3 years ago
parent
commit
e1ed3f3901
2 changed files with 50 additions and 19 deletions
  1. +22
    -1
      app.py
  2. +28
    -18
      templates/list.html

+ 22
- 1
app.py View File

@ -1,4 +1,4 @@
from flask import Flask, request, render_template, send_from_directory, abort, redirect, session, url_for
from flask import Flask, request, render_template, send_from_directory, abort, redirect, session, url_for, send_file
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from flask_limiter import Limiter from flask_limiter import Limiter
from flask_limiter.util import get_remote_address from flask_limiter.util import get_remote_address
@ -9,8 +9,10 @@ from mastodon import Mastodon
from datetime import date, datetime from datetime import date, datetime
from functools import wraps from functools import wraps
import hashlib import hashlib
from zipfile import ZipFile
import random import random
import os import os
import re
from config import C from config import C
app = Flask(__name__) app = Flask(__name__)
@ -47,6 +49,9 @@ class Paper(db.Model):
down_num = db.Column(db.Integer, index=True, default=0) down_num = db.Column(db.Integer, index=True, default=0)
file_hash = db.Column(db.String(64)) file_hash = db.Column(db.String(64))
# always increment 1 for the id of a new record
__table_args__ = { 'sqlite_autoincrement': True }
def is_downloaded(self): def is_downloaded(self):
return bool(DownloadRelation.query.filter_by(paper_id=self.id, username=session.get('username')).count()) return bool(DownloadRelation.query.filter_by(paper_id=self.id, username=session.get('username')).count())
@ -216,6 +221,10 @@ def upload(username):
return redirect('.#part2') return redirect('.#part2')
@app.route('/pastExam/test')
def test_download():
return send_file('/tmp/id.zip', as_attachment=True, attachment_filename='name.zip')
@app.route('/pastExam/<pid>/download') @app.route('/pastExam/<pid>/download')
@login_required() @login_required()
def download(pid, username): def download(pid, username):
@ -229,6 +238,18 @@ def download(pid, username):
p.down_num += 1 p.down_num += 1
db.session.commit() db.session.commit()
if request.args.get('type') == 'zip':
target_file = '/tmp/%s.zip' % pid
if not os.path.exists(target_file):
ipfs_client.get(p.file_hash, target='/tmp')
with ZipFile(target_file, 'w') as z:
for fname in os.listdir(os.path.join('/tmp', p.file_hash)):
z.write(os.path.join('/tmp', p.file_hash, fname), fname)
filename = re.sub('[^\w@_()()-]', '_', '%s_%s_共享计划_%d' %(p.course, p.teacher, p.id)) + '.zip'
return send_file(target_file, as_attachment=True, attachment_filename=filename)
return redirect(C.ipfs_base_url + p.file_hash, code=301) # 301减少不必要的请求 return redirect(C.ipfs_base_url + p.file_hash, code=301) # 301减少不必要的请求
@app.route('/pastExam/<pid>/like', methods=['POST', 'DELETE']) @app.route('/pastExam/<pid>/like', methods=['POST', 'DELETE'])

+ 28
- 18
templates/list.html View File

@ -234,21 +234,21 @@
<img class="rounded-circle" src="{{avatar}}" width="24"> <img class="rounded-circle" src="{{avatar}}" width="24">
<span class="username ml-2">{{username}}</span> <span class="username ml-2">{{username}}</span>
</button> </button>
<button type="button" class="btn btn-dark rounded-0 dropdown-toggle dropdown-toggle-split" id="dropdownMenuReference" data-toggle="dropdown" data-reference="parent">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="?my_upload=1#part2">我的上传</a>
<a class="dropdown-item" href="?my_fav=1#part2">我的点赞</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="login">切换帐号</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item wechat-share" href="##">
微信传播
<div><img src="img/wechat-share.png"></div>
</a>
</div>
</div>
<button type="button" class="btn btn-dark rounded-0 dropdown-toggle dropdown-toggle-split" id="dropdownMenuReference" data-toggle="dropdown" data-reference="parent">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="?my_upload=1#part2">我的上传</a>
<a class="dropdown-item" href="?my_fav=1#part2">我的点赞</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="login">切换帐号</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item wechat-share" href="##">
微信传播
<div><img src="img/wechat-share.png"></div>
</a>
</div>
</div>
</div> </div>
<div class="part1 new"> <div class="part1 new">
@ -390,9 +390,19 @@
<button class="btn btn-link" id="like-{{p.id}}" onclick="like('{{p.id}}')"> <button class="btn btn-link" id="like-{{p.id}}" onclick="like('{{p.id}}')">
<span class="num-info {{'num-info-active' if p.is_liked() else ''}}">好评(<span>{{p.like_num}}</span>)</span> <span class="num-info {{'num-info-active' if p.is_liked() else ''}}">好评(<span>{{p.like_num}}</span>)</span>
</button> </button>
<a href="{{p.id}}/download?v={{ipfs_version}}" target="_blank" class="btn btn-link pl-0" id="download-{{p.id}}">
<span class="num-info {{'num-info-active' if p.is_downloaded() else ''}}">去下载({{p.down_num}})</sp>
</a>
<span>
<a href="{{p.id}}/download?v={{ipfs_version}}" target="_blank" class="btn btn-link pl-0 pr-0" id="download-{{p.id}}">
<span class="num-info {{'num-info-active' if p.is_downloaded() else ''}}">去下载({{p.down_num}})</span>
</a>
<button type="button" class="btn btn-link pl-0 dropdown-toggle dropdown-toggle-split" id="downloadDropdownMenuReference" data-toggle="dropdown" data-reference="parent">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu" style="min-width: 5rem">
<a class="dropdown-item" href="{{p.id}}/download?type=zip" target="_blank" id="download-zip-{{p.id}}">
<span class="num-info">打包下载</span>
</a>
</div>
</span>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

Loading…
Cancel
Save