mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-12 13:24:52 +00:00
upload a new version of a file
This commit is contained in:
@@ -169,6 +169,7 @@
|
|||||||
<li><a class="op file-rename" href="#" data="{{ dirent.obj_name }}">重命名</a></li>
|
<li><a class="op file-rename" href="#" data="{{ dirent.obj_name }}">重命名</a></li>
|
||||||
<li><a class="op file-mv" href="#" data="{{ dirent.obj_name }}">移动</a></li>
|
<li><a class="op file-mv" href="#" data="{{ dirent.obj_name }}">移动</a></li>
|
||||||
<li><a class="op file-cp" href="#" data="{{ dirent.obj_name }}">复制</a></li>
|
<li><a class="op file-cp" href="#" data="{{ dirent.obj_name }}">复制</a></li>
|
||||||
|
<li><a class="op file-update" href="{{ SITE_ROOT }}repo/update_file/{{repo.id}}/?p={{ path }}{{dirent.obj_name}}">更新</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -281,7 +282,7 @@ $('.file-rename, .dir-rename').click(function () {
|
|||||||
$('#rename-form').modal({appendTo:'#main'});
|
$('#rename-form').modal({appendTo:'#main'});
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
var accessible_repos = [];
|
var accessible_repos = [];
|
||||||
{% for repo in accessible_repos %}
|
{% for repo in accessible_repos %}
|
||||||
{% if repo.props.has_subdir %}
|
{% if repo.props.has_subdir %}
|
||||||
|
111
templates/repo_update_file.html
Normal file
111
templates/repo_update_file.html
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
{% extends "myhome_base.html" %}
|
||||||
|
{% load seahub_tags %}
|
||||||
|
|
||||||
|
{% block info_bar_message %}
|
||||||
|
{% if request.user.is_authenticated %}
|
||||||
|
{{ block.super }}
|
||||||
|
{% else %}
|
||||||
|
<div id="info-bar">
|
||||||
|
<span class="info">当前链接会在短期内失效,欢迎您 <a href="http://seafile.com/" target="_blank">加入Seafile </a>体验更多功能。</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block main_panel %}
|
||||||
|
{% if used_space < total_space %}
|
||||||
|
<div class="upload-file-panel">
|
||||||
|
<h3>更新文件
|
||||||
|
{% for name, link in zipped %}
|
||||||
|
{% if not forloop.last %}
|
||||||
|
<a href="{{ SITE_ROOT }}repo/{{ repo.id }}/?p={{ link|urlencode }}">{{ name }}</a> /
|
||||||
|
{% else %}
|
||||||
|
{{ name }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %} <br />
|
||||||
|
(最大不得超过 {{ max_upload_file_size|filesizeformat }})
|
||||||
|
</h3>
|
||||||
|
<form id="upload-file-form" enctype="multipart/form-data" method="post">
|
||||||
|
<input type="hidden" name="target_file" value="{{ target_file }}" />
|
||||||
|
<input type="file" name="file" id="file" /><br />
|
||||||
|
<p id="error-msg" class="error">{{ error_msg }}</p>
|
||||||
|
<input id="upload-submit" type="submit" value="提交" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="upload-progress" class="hide">
|
||||||
|
<p>上传进度: <span id="upload-progress-text">获取中,请稍侯...</span></p>
|
||||||
|
<div id="task-progress-bar" class="hide"></div>
|
||||||
|
<button id="upload-cancel">取消</button>
|
||||||
|
</div>
|
||||||
|
<iframe id="request-progress" class="hide"><!--for chrome--></iframe>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="text-panel">
|
||||||
|
<p class="error">您的空间已经用完。</p>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_script %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
function gen_uuid() {
|
||||||
|
var uuid = "";
|
||||||
|
for (var i=0; i < 32; i++) {
|
||||||
|
uuid += Math.floor(Math.random() * 16).toString(16);
|
||||||
|
}
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: In order to real time show upload progress, we must deploy seahub in
|
||||||
|
// ngnix or gunicorn, since we need more than one seahub process to be
|
||||||
|
// running: one for receiving file, one for handling ajax request.
|
||||||
|
function submit_and_real_time_show () {
|
||||||
|
var form = $('#upload-file-form')[0],
|
||||||
|
uuid = gen_uuid(); // id for this upload so we can fetch progress info.
|
||||||
|
$('#upload-progress').removeClass('hide');
|
||||||
|
|
||||||
|
// Append X-Progress-ID uuid form action
|
||||||
|
form.action += (form.action.indexOf('?') == -1 ? '?' : '&') + 'X-Progress-ID=' + uuid;
|
||||||
|
form.submit();
|
||||||
|
$('#upload-submit').addClass('hide');
|
||||||
|
|
||||||
|
// Update progress bar: not work in chrome. for ff.
|
||||||
|
function update_progress_info() {
|
||||||
|
$.ajax({
|
||||||
|
url: '{{ SITE_ROOT }}file_upload_progress/?X-Progress-ID=' + uuid,
|
||||||
|
dataType: 'json',
|
||||||
|
cache: false,
|
||||||
|
contentType: 'application/json; charset=utf-8',
|
||||||
|
success: function(data) {
|
||||||
|
if (data) {
|
||||||
|
$('#upload-progress-text').html(filesizeformat(data.uploaded) + ' / ' + filesizeformat(data.length));
|
||||||
|
$('#task-progress-bar').removeClass('hide').progressbar({
|
||||||
|
value: data.uploaded / data.length * 100
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTimeout(update_progress_info, 1000);
|
||||||
|
};
|
||||||
|
update_progress_info();
|
||||||
|
|
||||||
|
// Update progress bar: for chrome
|
||||||
|
$('#request-progress').attr('src', '{{ SITE_ROOT }}file_upload_progress_page/?uuid=' + uuid);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$('#upload-submit').click(function () {
|
||||||
|
if (!$.trim($('#file').val())) {
|
||||||
|
$('#error-msg').html('请先选择一个文件');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$('#error-msg').addClass('hide');
|
||||||
|
submit_and_real_time_show();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#upload-cancel').click(function() {
|
||||||
|
location.reload(true);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
3
urls.py
3
urls.py
@@ -12,7 +12,7 @@ from seahub.views import root, peers, myhome, \
|
|||||||
seafile_access_check, back_local, repo_history_changes, \
|
seafile_access_check, back_local, repo_history_changes, \
|
||||||
repo_upload_file, file_upload_progress, file_upload_progress_page, get_subdir, file_move, \
|
repo_upload_file, file_upload_progress, file_upload_progress_page, get_subdir, file_move, \
|
||||||
repo_new_dir, repo_rename_file, validate_filename, \
|
repo_new_dir, repo_rename_file, validate_filename, \
|
||||||
repo_create
|
repo_create, repo_update_file
|
||||||
from seahub.notifications.views import notification_list
|
from seahub.notifications.views import notification_list
|
||||||
from seahub.share.views import share_admin
|
from seahub.share.views import share_admin
|
||||||
from seahub.group.views import group_list
|
from seahub.group.views import group_list
|
||||||
@@ -50,6 +50,7 @@ urlpatterns = patterns('',
|
|||||||
(r'^repo/upload_check/$', validate_filename),
|
(r'^repo/upload_check/$', validate_filename),
|
||||||
(r'^repo/file_rename/$', repo_rename_file),
|
(r'^repo/file_rename/$', repo_rename_file),
|
||||||
url(r'^repo/upload_file/(?P<repo_id>[^/]+)/$', repo_upload_file, name='repo_upload_file'),
|
url(r'^repo/upload_file/(?P<repo_id>[^/]+)/$', repo_upload_file, name='repo_upload_file'),
|
||||||
|
url(r'^repo/update_file/(?P<repo_id>[^/]+)/$', repo_update_file, name='repo_update_file'),
|
||||||
url(r'^repo/(?P<repo_id>[^/]+)/$', repo, name='repo'),
|
url(r'^repo/(?P<repo_id>[^/]+)/$', repo, name='repo'),
|
||||||
(r'^repo/history/(?P<repo_id>[^/]+)/$', repo_history),
|
(r'^repo/history/(?P<repo_id>[^/]+)/$', repo_history),
|
||||||
(r'^repo/history/revert/(?P<repo_id>[^/]+)/$', repo_history_revert),
|
(r'^repo/history/revert/(?P<repo_id>[^/]+)/$', repo_history_revert),
|
||||||
|
105
views.py
105
views.py
@@ -144,9 +144,10 @@ def access_to_repo(request, repo_id, repo_ap):
|
|||||||
def gen_path_link(path, repo_name):
|
def gen_path_link(path, repo_name):
|
||||||
"""
|
"""
|
||||||
Generate navigate paths and links in repo page.
|
Generate navigate paths and links in repo page.
|
||||||
Note: `path` must be end with '/'.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if path[-1:] != '/':
|
||||||
|
path += '/'
|
||||||
paths = []
|
paths = []
|
||||||
links = []
|
links = []
|
||||||
if path and path != '/':
|
if path and path != '/':
|
||||||
@@ -279,9 +280,9 @@ def repo_upload_file(request, repo_id):
|
|||||||
used_space = seafserv_threaded_rpc.get_user_quota_usage(request.user.username)
|
used_space = seafserv_threaded_rpc.get_user_quota_usage(request.user.username)
|
||||||
############ GET ############
|
############ GET ############
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
parent_dir = request.GET.get('p', '/')
|
parent_dir = request.GET.get('p', '/')
|
||||||
zipped = gen_path_link (parent_dir, repo.name)
|
zipped = gen_path_link (parent_dir, repo.name)
|
||||||
# TODO: per user quota
|
# TODO: per user quota, org user quota
|
||||||
return render_to_response ('repo_upload_file.html', {
|
return render_to_response ('repo_upload_file.html', {
|
||||||
"repo": repo,
|
"repo": repo,
|
||||||
"parent_dir": parent_dir,
|
"parent_dir": parent_dir,
|
||||||
@@ -335,8 +336,8 @@ def repo_upload_file(request, repo_id):
|
|||||||
return go_error(request, error_msg)
|
return go_error(request, error_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.put_file (repo_id, tmp_file_path, parent_dir,
|
seafserv_threaded_rpc.post_file (repo_id, tmp_file_path, parent_dir,
|
||||||
filename, request.user.username);
|
filename, request.user.username);
|
||||||
except SearpcError, e:
|
except SearpcError, e:
|
||||||
remove_tmp_file()
|
remove_tmp_file()
|
||||||
error_msg = e.msg
|
error_msg = e.msg
|
||||||
@@ -345,6 +346,81 @@ def repo_upload_file(request, repo_id):
|
|||||||
remove_tmp_file()
|
remove_tmp_file()
|
||||||
url = reverse('repo', args=[repo_id]) + ('?p=%s' % parent_dir)
|
url = reverse('repo', args=[repo_id]) + ('?p=%s' % parent_dir)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def repo_update_file(request, repo_id):
|
||||||
|
repo = get_repo(repo_id)
|
||||||
|
total_space = settings.USER_TOTAL_SPACE
|
||||||
|
used_space = seafserv_threaded_rpc.get_user_quota_usage(request.user.username)
|
||||||
|
############ GET ############
|
||||||
|
if request.method == 'GET':
|
||||||
|
target_file = request.GET.get('p')
|
||||||
|
if not target_file:
|
||||||
|
return go_error(request)
|
||||||
|
zipped = gen_path_link (target_file, repo.name)
|
||||||
|
# TODO: per user quota, org user quota
|
||||||
|
return render_to_response ('repo_update_file.html', {
|
||||||
|
"repo": repo,
|
||||||
|
"target_file": target_file,
|
||||||
|
"used_space": used_space,
|
||||||
|
"total_space": total_space,
|
||||||
|
"zipped": zipped,
|
||||||
|
"max_upload_file_size": settings.MAX_UPLOAD_FILE_SIZE,
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
############ POST ############
|
||||||
|
target_file = request.POST.get('target_file')
|
||||||
|
if not target_file:
|
||||||
|
return go_error(request)
|
||||||
|
|
||||||
|
def render_update_file_error(error_msg):
|
||||||
|
zipped = gen_path_link (target_file, repo.name)
|
||||||
|
return render_to_response ('repo_update.html', {
|
||||||
|
"error_msg": error_msg,
|
||||||
|
"repo": repo,
|
||||||
|
"used_space": used_space,
|
||||||
|
"total_space": total_space,
|
||||||
|
"zipped": zipped,
|
||||||
|
"target_file": target_file,
|
||||||
|
"max_upload_file_size": settings.MAX_UPLOAD_FILE_SIZE,
|
||||||
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
try:
|
||||||
|
tmp_file = request.FILES['file']
|
||||||
|
except:
|
||||||
|
error_msg = u'请选择一个文件'
|
||||||
|
return render_update_file_error(error_msg)
|
||||||
|
|
||||||
|
tmp_file_path = tmp_file.temporary_file_path()
|
||||||
|
if not os.access(tmp_file_path, os.F_OK):
|
||||||
|
error_msg = u'上传文件失败'
|
||||||
|
return render_update_file_error(error_msg)
|
||||||
|
|
||||||
|
def remove_tmp_file():
|
||||||
|
try:
|
||||||
|
os.remove(tmp_file.temporary_file_path())
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if tmp_file.size > settings.MAX_UPLOAD_FILE_SIZE:
|
||||||
|
error_msg = u"您上传的文件太大"
|
||||||
|
remove_tmp_file()
|
||||||
|
return go_error(request, error_msg)
|
||||||
|
|
||||||
|
parent_dir = os.path.dirname(target_file)
|
||||||
|
filename = os.path.basename(target_file)
|
||||||
|
|
||||||
|
try:
|
||||||
|
seafserv_threaded_rpc.put_file (repo_id, tmp_file_path, parent_dir,
|
||||||
|
filename, request.user.username);
|
||||||
|
except SearpcError, e:
|
||||||
|
remove_tmp_file()
|
||||||
|
error_msg = e.msg
|
||||||
|
return render_update_file_error(error_msg)
|
||||||
|
else:
|
||||||
|
remove_tmp_file()
|
||||||
|
url = reverse('repo', args=[repo_id]) + ('?p=%s' % parent_dir)
|
||||||
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
def get_subdir(request):
|
def get_subdir(request):
|
||||||
repo_id = request.GET.get('repo_id', '')
|
repo_id = request.GET.get('repo_id', '')
|
||||||
@@ -794,8 +870,6 @@ def repo_view_file(request, repo_id, obj_id):
|
|||||||
|
|
||||||
# generate path and link
|
# generate path and link
|
||||||
path = request.GET.get('p', '/')
|
path = request.GET.get('p', '/')
|
||||||
if path[-1] != '/':
|
|
||||||
path = path + '/'
|
|
||||||
zipped = gen_path_link(path, repo.name)
|
zipped = gen_path_link(path, repo.name)
|
||||||
|
|
||||||
# filename
|
# filename
|
||||||
@@ -1458,7 +1532,7 @@ def repo_new_dir(request):
|
|||||||
new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name)
|
new_dir_name = check_filename_with_rename(repo_id, parent_dir, new_dir_name)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.put_dir(repo_id, parent_dir, new_dir_name, user)
|
seafserv_threaded_rpc.post_dir(repo_id, parent_dir, new_dir_name, user)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
return go_error(request, str(e))
|
return go_error(request, str(e))
|
||||||
|
|
||||||
@@ -1540,13 +1614,19 @@ def repo_create(request):
|
|||||||
error_msg = ""
|
error_msg = ""
|
||||||
if not repo_name:
|
if not repo_name:
|
||||||
error_msg = u"目录名不能为空"
|
error_msg = u"目录名不能为空"
|
||||||
|
elif len(repo_name) > 50:
|
||||||
|
error_msg = u"目录名太长"
|
||||||
elif not repo_desc:
|
elif not repo_desc:
|
||||||
error_msg = u"描述不能为空"
|
error_msg = u"描述不能为空"
|
||||||
|
elif len(repo_desc) > 100:
|
||||||
|
error_msg = u"描述太长"
|
||||||
elif encrypted == 'on':
|
elif encrypted == 'on':
|
||||||
if not passwd:
|
if not passwd:
|
||||||
error_msg = u"密码不能为空"
|
error_msg = u"密码不能为空"
|
||||||
elif not passwd_again:
|
elif not passwd_again:
|
||||||
error_msg = u"确认密码不能为空"
|
error_msg = u"确认密码不能为空"
|
||||||
|
elif len(passwd) < 3:
|
||||||
|
error_msg = u"密码太短"
|
||||||
elif len(passwd) > 15:
|
elif len(passwd) > 15:
|
||||||
error_msg = u"密码太长"
|
error_msg = u"密码太长"
|
||||||
elif passwd != passwd_again:
|
elif passwd != passwd_again:
|
||||||
@@ -1556,10 +1636,13 @@ def repo_create(request):
|
|||||||
return render_repo_create_error(error_msg)
|
return render_repo_create_error(error_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
seafserv_threaded_rpc.create_repo(repo_name, repo_desc,
|
repo_id = seafserv_threaded_rpc.create_repo(repo_name, repo_desc,
|
||||||
request.user.username, passwd)
|
request.user.username, passwd)
|
||||||
except:
|
except:
|
||||||
error_msg = u"两次输入的密码不相同"
|
error_msg = u"创建目录失败"
|
||||||
return render_repo_create_error(error_msg)
|
return render_repo_create_error(error_msg)
|
||||||
else:
|
else:
|
||||||
|
if not repo_id:
|
||||||
|
error_msg = u"创建目录失败"
|
||||||
|
return render_repo_create_error(error_msg)
|
||||||
return HttpResponseRedirect(reverse(myhome))
|
return HttpResponseRedirect(reverse(myhome))
|
||||||
|
Reference in New Issue
Block a user