diff --git a/seahub/api2/endpoints/dirents_download_link.py b/seahub/api2/endpoints/dirents_download_link.py
new file mode 100644
index 0000000000..f1ff619b30
--- /dev/null
+++ b/seahub/api2/endpoints/dirents_download_link.py
@@ -0,0 +1,88 @@
+import logging
+import json
+import posixpath
+
+from rest_framework.authentication import SessionAuthentication
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.response import Response
+from rest_framework.views import APIView
+from rest_framework import status
+
+from seahub.api2.throttling import UserRateThrottle
+from seahub.api2.authentication import TokenAuthentication
+from seahub.api2.utils import api_error
+
+from seahub.utils import string2list, get_fileserver_root
+from seahub.views import check_folder_permission
+from seahub.views.file import send_file_access_msg
+
+from seaserv import seafile_api
+from pysearpc import SearpcError
+
+logger = logging.getLogger(__name__)
+
+class DirentsDownloadLinkView(APIView):
+ """
+ Download multi files/dirs.
+ """
+
+ authentication_classes = (TokenAuthentication, SessionAuthentication)
+ permission_classes = (IsAuthenticated, )
+ throttle_classes = (UserRateThrottle, )
+
+ def get(self, request, repo_id, format=None):
+
+ repo = seafile_api.get_repo(repo_id)
+ if not repo:
+ error_msg = 'Library %s not found.' % repo_id
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ # argument checking
+ parent_dir = request.GET.get('parent_dir', None)
+ dirent_name_string = request.GET.get('dirents', None)
+
+ if not parent_dir:
+ error_msg = 'parent_dir invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ if not dirent_name_string:
+ error_msg = 'dirents invalid.'
+ return api_error(status.HTTP_400_BAD_REQUEST, error_msg)
+
+ # folder exist checking
+ if not seafile_api.get_dir_id_by_path(repo_id, parent_dir):
+ error_msg = 'Folder %s not found.' % parent_dir
+ return api_error(status.HTTP_404_NOT_FOUND, error_msg)
+
+ # permission checking
+ if check_folder_permission(request, repo_id, parent_dir) is None:
+ error_msg = 'Permission denied.'
+ return api_error(status.HTTP_403_FORBIDDEN, error_msg)
+
+ dirent_name_list = string2list(dirent_name_string)
+ dirent_list = []
+ for dirent_name in dirent_name_list:
+ dirent_list.append(dirent_name.strip('/'))
+
+ fake_obj_id = {}
+ fake_obj_id['file_list'] = dirent_list
+ fake_obj_id['parent_dir'] = parent_dir
+
+ username = request.user.username
+ try:
+ token = seafile_api.get_fileserver_access_token(repo_id,
+ json.dumps(fake_obj_id), 'download-multi', username, False)
+ except SearpcError as e:
+ logger.error(e)
+ error_msg = 'Internal Server Error'
+ return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
+
+ if len(dirent_list) > 10:
+ send_file_access_msg(request, repo, parent_dir, 'web')
+ else:
+ for dirent_name in dirent_list:
+ full_dirent_path = posixpath.join(parent_dir, dirent_name)
+ send_file_access_msg(request, repo, full_dirent_path, 'web')
+
+ download_url = '%s/files/%s' % (get_fileserver_root(), token)
+ return Response({'url': download_url})
diff --git a/seahub/templates/js/templates.html b/seahub/templates/js/templates.html
index 3d7c5ef9b4..fee286c830 100644
--- a/seahub/templates/js/templates.html
+++ b/seahub/templates/js/templates.html
@@ -99,6 +99,7 @@
+
diff --git a/seahub/urls.py b/seahub/urls.py
index ef461f0e65..d295f1022c 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -24,6 +24,7 @@ from seahub.api2.endpoints.upload_links import UploadLinks, UploadLink
from seahub.api2.endpoints.file import FileView
from seahub.api2.endpoints.dir import DirView
from seahub.api2.endpoints.repo_set_password import RepoSetPassword
+from seahub.api2.endpoints.dirents_download_link import DirentsDownloadLinkView
from seahub.api2.endpoints.admin.login import Login
from seahub.api2.endpoints.admin.file_audit import FileAudit
from seahub.api2.endpoints.admin.file_update import FileUpdate
@@ -189,8 +190,9 @@ urlpatterns = patterns(
url(r'^api/v2.1/share-link/(?P[a-f0-9]{10})/$', ShareLink.as_view(), name='api-v2.1-share-link'),
url(r'^api/v2.1/upload-links/$', UploadLinks.as_view(), name='api-v2.1-upload-links'),
url(r'^api/v2.1/upload-link/(?P[a-f0-9]{10})/$', UploadLink.as_view(), name='api-v2.1-upload-link'),
- url(r'^api/v2.1/repos/(?P[-0-9-a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'),
- url(r'^api/v2.1/repos/(?P[-0-9-a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
+ url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/file/$', FileView.as_view(), name='api-v2.1-file-view'),
+ url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/dirents/download-link/$', DirentsDownloadLinkView.as_view(), name='api-v2.1-dirents-download-link-view'),
+ url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/dir/$', DirView.as_view(), name='api-v2.1-dir-view'),
url(r'^api/v2.1/repos/(?P[-0-9a-f]{36})/set-password/$', RepoSetPassword.as_view(), name="api-v2.1-repo-set-password"),
url(r'^api/v2.1/admin/sysinfo/$', SysInfo.as_view(), name='api-v2.1-sysinfo'),
url(r'^api/v2.1/admin/devices/$', AdminDevices.as_view(), name='api-v2.1-admin-devices'),
diff --git a/static/scripts/app/views/dir.js b/static/scripts/app/views/dir.js
index f9304366a6..24dd0016c6 100644
--- a/static/scripts/app/views/dir.js
+++ b/static/scripts/app/views/dir.js
@@ -466,6 +466,7 @@ define([
'click #mv-dirents': 'mv',
'click #cp-dirents': 'cp',
'click #del-dirents': 'del',
+ 'click #download-dirents': 'download',
'click .by-name': 'sortByName',
'click .by-time': 'sortByTime',
'click .basic-upload-btn': 'uploadFile',
@@ -799,6 +800,30 @@ define([
}
},
+ download: function () {
+ var dirents = this.dir,
+ selected_dirents = dirents.where({'selected':true}),
+ selected_names = '';
+
+ $(selected_dirents).each(function() {
+ selected_names += this.get('obj_name') + ',';
+ });
+
+ $.ajax({
+ url: Common.getUrl({
+ name: 'download_dirents',
+ repo_id: dirents.repo_id
+ }) + '?parent_dir=' + encodeURIComponent(dirents.path) + '&dirents=' + encodeURIComponent(selected_names),
+ dataType: 'json',
+ success: function(data) {
+ location.href = data['url'];
+ },
+ error: function (xhr) {
+ Common.ajaxErrorHandler(xhr);
+ }
+ });
+ },
+
del: function () {
var dirents = this.dir;
var _this = this;
diff --git a/static/scripts/common.js b/static/scripts/common.js
index 9a0429c910..25610e08cd 100644
--- a/static/scripts/common.js
+++ b/static/scripts/common.js
@@ -80,6 +80,7 @@ define([
case 'unstar_file': return siteRoot + 'ajax/repo/' + options.repo_id + '/file/unstar/';
case 'del_dir': return siteRoot + 'api2/repos/' + options.repo_id + '/dir/';
case 'del_file': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/file/';
+ case 'download_dirents': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/dirents/download-link/';
case 'rename_dir': return siteRoot + 'api2/repos/' + options.repo_id + '/dir/';
case 'rename_file': return siteRoot + 'api/v2.1/repos/' + options.repo_id + '/file/';
case 'mv_dir': return siteRoot + 'ajax/repo/' + options.repo_id + '/dir/mv/';
diff --git a/tests/api/endpoints/test_dirents_download_link.py b/tests/api/endpoints/test_dirents_download_link.py
new file mode 100644
index 0000000000..f69a9b77a7
--- /dev/null
+++ b/tests/api/endpoints/test_dirents_download_link.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+import os
+import json
+
+from django.core.urlresolvers import reverse
+
+from seahub.test_utils import BaseTestCase
+
+try:
+ from seahub.settings import LOCAL_PRO_DEV_ENV
+except ImportError:
+ LOCAL_PRO_DEV_ENV = False
+
+
+class DirentsDownloadLinkViewTest(BaseTestCase):
+
+ def setUp(self):
+ self.repo_id = self.repo.id
+
+ self.file_path = self.file
+ self.file_name = os.path.basename(self.file_path)
+
+ self.folder_path = self.folder
+ self.folder_name = os.path.basename(self.folder_path)
+
+ self.url = reverse('api-v2.1-dirents-download-link-view', args=[self.repo_id])
+
+ def tearDown(self):
+ self.remove_repo()
+
+ def test_can_get_download_url(self):
+ self.login_as(self.user)
+ parent_dir = '/'
+ dirents = self.file_name + ',' + self.folder_name
+ url = self.url + '?parent_dir=%s&dirents=%s' % (parent_dir, dirents)
+
+ resp = self.client.get(url)
+ self.assertEqual(200, resp.status_code)
+ json_resp = json.loads(resp.content)
+ assert '8082' in json_resp['url']
+
+ def test_args_invalid(self):
+ self.login_as(self.user)
+ parent_dir = '/'
+ dirents = self.file_name + ',' + self.folder_name
+
+ url = self.url + '?prent_dir=%s&dirents=%s' % (parent_dir, dirents)
+ resp = self.client.get(url)
+ self.assertEqual(400, resp.status_code)
+
+ url = self.url + '?parent_dir=%s&dirent=%s' % (parent_dir, dirents)
+ resp = self.client.get(url)
+ self.assertEqual(400, resp.status_code)
+
+ url = self.url + '?parent_dir=%s&dirents=%s' % (parent_dir+'invalid', dirents)
+ resp = self.client.get(url)
+ self.assertEqual(404, resp.status_code)
+
+ def test_permission_invalid(self):
+ self.login_as(self.admin)
+ parent_dir = '/'
+ dirents = self.file_name + ',' + self.folder_name
+
+ url = self.url + '?parent_dir=%s&dirents=%s' % (parent_dir, dirents)
+ resp = self.client.get(url)
+ self.assertEqual(403, resp.status_code)