1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-31 22:54:11 +00:00

Add file preview feature

This commit is contained in:
xiez
2012-07-02 22:45:21 +08:00
parent 211893e0b7
commit 340ad516e4
7 changed files with 212 additions and 5 deletions

View File

@@ -582,3 +582,15 @@ table img {
#upload-cancel {
margin-top:8px;
}
/* file preview */
#file-content {
border: 1px solid #999;
padding: 5px;
min-height: 200px;
white-space: pre-wrap; /* css-3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}

View File

@@ -170,6 +170,13 @@ USE_SUBDOMAIN = False
# account type is `personal` or `business`
ACCOUNT_TYPE = 'personal'
FILE_PREVIEW_MAX_SIZE = 10 * 1024 * 1024
PREVIEW_FILEEXT = {
'Document': ('ac', 'am', 'as', 'as3', 'asm', 'bat', 'c', 'cc', 'cmake', 'cpp', 'cs', 'css', 'csv', 'cxx', 'diff', 'erb', 'groovy', 'gsheet', 'h', 'haml', 'hh', 'htm', 'html', 'java', 'js', 'less', 'm', 'make', 'ml', 'mm', 'ods', 'odt', 'php', 'pl', 'properties', 'py', 'rb', 'rtf', 'sass', 'scala', 'scm', 'script', 'sh', 'sml', 'sql', 'txt', 'vi', 'vim', 'wpd', 'xls', 'xlsm', 'xlsx', 'xml', 'xsd', 'xsl', 'xslt', 'yaml'),
'Image': ('ai', 'bmp', 'eps', 'gif', 'ind', 'jpeg', 'jpg', 'png', 'ps', 'psd', 'tif', 'tiff'),
}
try:
import local_settings
except ImportError:

View File

@@ -104,7 +104,7 @@
{% for dirent in file_list %}
<tr>
<td class="icon-container"><img src="{{ MEDIA_URL }}img/{{ dirent.obj_name|file_icon_filter }}" alt="文件" /></td>
<td><a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&op=view">{{ dirent.props.obj_name }}</a></td>
<td><a class="op" href="{{ SITE_ROOT }}repo/{{ repo.props.id }}/view/{{ dirent.props.obj_id }}/?file_name={{ dirent.props.obj_name }}&p={{ path|urlencode }}{{ dirent.obj_name|urlencode }}">{{ dirent.props.obj_name }}</a></td>
<td>{{ dirent.file_size|filesizeformat }}</td>
<td>
<img src="{{ MEDIA_URL }}img/more-option.png" alt="更多操作" class="more-op hide" />

View File

@@ -0,0 +1,71 @@
{% 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 %}
<h2 class="subject">
{{repo.props.name}}
</h2>
<div class="side fright">
<h3>操作</h3>
<p><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=view" target="_blank">查看原始文件</a></p>
<p><a href="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=download" target="_blank">下载文件</a></p>
</div>
<div class="main fleft">
<p class="path">
当前路径:
{% 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 %}
</p>
<pre id="file-content">正在读取文件内容...</pre>
</div>
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
$(window).load(function() {
var can_preview = "{{ can_preview }}";
var filetype = "{{ filetype }}";
if (can_preview == 'True' && filetype == 'Document') {
$.ajax({
url: '{{ SITE_ROOT }}repo/{{ repo.id }}/view/{{ obj_id }}/?file_name={{ file_name }}&t={{ token }}',
dataType: 'json',
cache: false,
contentType: 'application/json; charset=utf-8',
success: function(data) {
if (data.length > 0) {
$('#file-content').html(data[0]['content']);
}
},
error: function(xhr, ajaxOptions, thrownError) {
var jsonVal = jQuery.parseJSON(xhr.responseText);
$('#file-content').html(jsonVal[0]['error']);
}
});
return false;
} else if (can_preview == 'True' && filetype == 'Image') {
$('#file-content').replaceWith('<img src="{{ raw_path }}" width="550" height="450"></img>');
} else {
$('#file-content').html('无法识别该文件格式,<a class="op" href="">下载文件</a>。');
}
});
</script>
{% endblock %}

View File

@@ -8,11 +8,10 @@ from seahub.views import root, peers, myhome, \
activate_user, user_add, user_remove, sys_group_admin, sys_org_admin, \
ownerhome, repo_history_dir, repo_history_revert, \
user_info, repo_set_access_property, repo_access_file, \
repo_remove_share, repo_download, org_info, \
repo_remove_share, repo_download, org_info, repo_view_file, \
seafile_access_check, back_local, repo_history_changes, \
repo_upload_file, file_upload_progress, file_upload_progress_page, get_subdir, file_move, \
repo_new_dir, repo_rename_file, validate_filename
from seahub.notifications.views import notification_list
from seahub.share.views import share_admin
from seahub.group.views import group_list
@@ -59,6 +58,8 @@ urlpatterns = patterns('',
# (r'^repo/removefetched/(?P<user_id>[^/]+)/(?P<repo_id>[^/]+)/$', remove_fetched_repo),
# (r'^repo/setap/(?P<repo_id>[^/]+)/$', repo_set_access_property),
(r'^repo/(?P<repo_id>[^/]+)/(?P<obj_id>[^/]+)/$', repo_access_file),
(r'^repo/(?P<repo_id>[^/]+)/view/(?P<obj_id>[^/]+)/$', repo_view_file),
(r'^download/repo/$', repo_download),
(r'^file/move/get_subdir/$', get_subdir),
(r'^file/move/$', file_move),

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
import settings
import os
import re
import time
import os
@@ -17,6 +18,9 @@ from seaserv import seafserv_rpc, ccnet_threaded_rpc, seafserv_threaded_rpc, \
EMPTY_SHA1 = '0000000000000000000000000000000000000000'
import settings
from settings import PREVIEW_FILEEXT
def go_permission_error(request, msg=None):
"""
Return permisson error page.
@@ -225,3 +229,14 @@ def get_accessible_repos(request, repo):
repo.props.has_subdir = check_has_subdir(repo)
return accessible_repos
def valid_previewed_file(filename):
"""
Check whether file can preview on web
"""
fileExt = os.path.splitext(filename)[1][1:]
for filetype in PREVIEW_FILEEXT.keys():
if fileExt in PREVIEW_FILEEXT.get(filetype):
return (True, filetype)
return (False, '')

105
views.py
View File

@@ -3,7 +3,9 @@ import settings
import os
import stat
import simplejson as json
import re
import sys
import urllib2
from urllib import quote
from django.core.urlresolvers import reverse
from django.core.mail import send_mail
@@ -34,9 +36,10 @@ from seahub.notifications.models import UserNotification
from forms import AddUserForm
from utils import go_permission_error, go_error, list_to_string, \
get_httpserver_root, get_ccnetapplet_root, gen_token, \
calculate_repo_last_modify, \
calculate_repo_last_modify, valid_previewed_file, \
check_filename_with_rename, get_accessible_repos, EMPTY_SHA1
from seahub.profile.models import Profile
from settings import FILE_PREVIEW_MAX_SIZE
@login_required
def root(request):
@@ -751,6 +754,104 @@ def repo_del_file(request, repo_id):
url = reverse('repo', args=[repo_id]) + ('?p=%s' % parent_dir)
return HttpResponseRedirect(url)
@login_required
def repo_view_file(request, repo_id, obj_id):
http_server_root = get_httpserver_root()
filename = urllib2.quote(request.GET.get('file_name', '').encode('utf-8'))
if request.is_ajax():
content_type = 'application/json; charset=utf-8'
token = request.GET.get('t')
tmp_str = '%s/access?repo_id=%s&id=%s&filename=%s&op=%s&t=%s&u=%s'
redirect_url = tmp_str % (http_server_root,
repo_id, obj_id,
filename, 'view',
token,
request.user.username)
try:
proxied_request = urllib2.urlopen(redirect_url)
if long(proxied_request.headers['Content-Length']) > FILE_PREVIEW_MAX_SIZE:
data = json.dumps([{'error': '文件超过10M无法在线查看。'}])
return HttpResponse(data, status=400, content_type=content_type)
else:
content = proxied_request.read()
except urllib2.HTTPError, e:
err = 'HTTPError: 无法在线打开该文件'
data = json.dumps([{'error': err}])
return HttpResponse(data, status=400, content_type=content_type)
except urllib2.URLError as e:
err = 'URLError: 无法在线打开该文件'
data = json.dumps([{'error': err}])
return HttpResponse(data, status=400, content_type=content_type)
else:
l, d = [], {}
try:
# XXX: file in windows is encoded in gbk
u_content = content.decode('gbk')
except:
u_content = content.decode('utf-8')
from django.utils.html import escape
d['content'] = re.sub("\r\n|\n", "<br />", escape(u_content))
l.append(d)
data = json.dumps(l)
return HttpResponse(data, status=200, content_type=content_type)
repo = get_repo(repo_id)
if not repo:
raise Http404
# if a repo doesn't have access property in db, then assume it's 'own'
repo_ap = seafserv_threaded_rpc.repo_query_access_property(repo_id)
if not repo_ap:
repo_ap = 'own'
# if a repo is shared to me, then I can view and download file no mater whether
# repo's access property is 'own' or 'public'
if check_shared_repo(request, repo_id):
share_to_me = True
else:
share_to_me = False
token = ''
if repo_ap == 'own':
# people who is owner or this repo is shared to him, can visit the repo;
# others, just go to 404 page
if validate_owner(request, repo_id) or share_to_me:
# owner should get a token to visit repo
token = gen_token()
# put token into memory in seaf-server
seafserv_rpc.web_save_access_token(token, obj_id)
else:
raise Http404
# generate path and link
path = request.GET.get('p', '/')
if path[-1] != '/':
path = path + '/'
zipped = gen_path_link(path, repo.name)
# filename
can_preview, filetype = valid_previewed_file(filename)
# raw path
tmp_str = '%s/access?repo_id=%s&id=%s&filename=%s&op=%s&t=%s&u=%s'
raw_path = tmp_str % (http_server_root,
repo_id, obj_id,
filename, 'view',
token,
request.user.username)
return render_to_response('repo_view_file.html', {
'repo': repo,
'obj_id': obj_id,
'file_name': filename,
'zipped': zipped,
'token': token,
'can_preview': can_preview,
'filetype': filetype,
'raw_path': raw_path,
}, context_instance=RequestContext(request))
def repo_access_file(request, repo_id, obj_id):
if repo_id:
repo = get_repo(repo_id)
@@ -807,7 +908,7 @@ def repo_access_file(request, repo_id, obj_id):
token,
request.user.username)
return HttpResponseRedirect(redirect_url)
@login_required
def repo_download(request):
repo_id = request.GET.get('repo_id', '')