Skip to content

Commit e084455

Browse files
author
zhuoyu.chen
committed
[fix] Fix the xls download stuck problem
1 parent f561be4 commit e084455

File tree

2 files changed

+35
-46
lines changed

2 files changed

+35
-46
lines changed

desktop/core/base_requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ kerberos==1.3.0
3939
kubernetes==26.1.0
4040
Mako==1.2.3
4141
Markdown==3.7
42-
openpyxl==3.0.9
42+
xlsxwriter==3.2.2
4343
phoenixdb==1.2.1
4444
prompt-toolkit==3.0.39
4545
protobuf==3.20.3

desktop/core/src/desktop/lib/export_csvxls.py

+34-45
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"""
1919
Common library to export either CSV or XLS.
2020
"""
21-
import gc
2221
import re
2322
import logging
2423
import numbers
@@ -27,7 +26,7 @@
2726

2827
import six
2928
import tablib
30-
import openpyxl
29+
import xlsxwriter
3130
from django.http import HttpResponse, StreamingHttpResponse
3231
from django.utils.encoding import smart_str
3332

@@ -36,42 +35,43 @@
3635
LOG = logging.getLogger()
3736

3837
DOWNLOAD_CHUNK_SIZE = 1 * 1024 * 1024 # 1MB
39-
ILLEGAL_CHARS = r'[\000-\010]|[\013-\014]|[\016-\037]'
38+
39+
ILLEGAL_CHARS_RE = re.compile(r'[\000-\010]|[\013-\014]|[\016-\037]')
40+
HYPERLINK_RE = re.compile(r'^(https?://.+)', re.IGNORECASE)
41+
4042
FORMAT_TO_CONTENT_TYPE = {
4143
'csv': 'application/csv',
4244
'xls': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
4345
'json': 'application/json'
4446
}
4547

46-
4748
def nullify(cell):
48-
return cell if cell is not None else "NULL"
49-
49+
return cell if cell is not None else "NULL"
5050

5151
def file_reader(fh):
52-
"""Generator that reads a file, chunk-by-chunk."""
53-
while True:
54-
chunk = fh.read(DOWNLOAD_CHUNK_SIZE)
55-
if not chunk:
56-
fh.close()
57-
break
58-
yield chunk
52+
"""Generator that reads a file, chunk-by-chunk."""
53+
while True:
54+
chunk = fh.read(DOWNLOAD_CHUNK_SIZE)
55+
if not chunk:
56+
fh.close()
57+
break
58+
yield chunk
5959

6060

6161
def encode_row(row, encoding=None, make_excel_links=False):
62-
encoded_row = []
63-
encoding = encoding or i18n.get_site_encoding()
62+
encoded_row = []
63+
encoding = encoding or i18n.get_site_encoding()
6464

65-
for cell in row:
66-
if isinstance(cell, six.string_types):
67-
cell = re.sub(ILLEGAL_CHARS, '?', cell)
68-
if make_excel_links:
69-
cell = re.compile('^(https?://.+)', re.IGNORECASE).sub(r'=HYPERLINK("\1")', cell)
70-
cell = nullify(cell)
71-
if not isinstance(cell, numbers.Number):
72-
cell = smart_str(cell, encoding, strings_only=True, errors='replace')
73-
encoded_row.append(cell)
74-
return encoded_row
65+
for cell in row:
66+
if isinstance(cell, six.string_types):
67+
cell = ILLEGAL_CHARS_RE.sub('?', cell)
68+
if make_excel_links:
69+
cell = HYPERLINK_RE.sub(r'=HYPERLINK("\1")', cell)
70+
cell = nullify(cell)
71+
if not isinstance(cell, numbers.Number):
72+
cell = smart_str(cell, encoding, strings_only=True, errors='replace')
73+
encoded_row.append(cell)
74+
return encoded_row
7575

7676

7777
def dataset(headers, data, encoding=None):
@@ -90,43 +90,32 @@ def dataset(headers, data, encoding=None):
9090

9191
return dataset
9292

93-
94-
class XlsWrapper(object):
95-
def __init__(self, xls):
96-
self.xls = xls
97-
98-
99-
def xls_dataset(workbook):
100-
output = string_io()
101-
workbook.save(output)
102-
output.seek(0)
103-
return XlsWrapper(output.read())
104-
105-
10693
def create_generator(content_generator, format, encoding=None):
10794
if format == 'csv':
10895
show_headers = True
10996
for headers, data in content_generator:
11097
yield dataset(show_headers and headers or None, data, encoding).csv
11198
show_headers = False
11299
elif format == 'xls':
113-
workbook = openpyxl.Workbook(write_only=True)
114-
worksheet = workbook.create_sheet()
100+
output = string_io()
101+
workbook = xlsxwriter.Workbook(output)
102+
worksheet = workbook.add_worksheet()
115103
row_ctr = 0
116104

117105
for _headers, _data in content_generator:
118106
# Write headers to workbook once
119107
if _headers and row_ctr == 0:
120-
worksheet.append(encode_row(_headers, encoding))
108+
worksheet.write_row(row_ctr, 0, encode_row(_headers, encoding, make_excel_links=False))
121109
row_ctr += 1
122110

123111
# Write row data to workbook
124112
for row in _data:
125-
worksheet.append(encode_row(row, encoding, make_excel_links=True))
113+
worksheet.write_row(row_ctr, 0, encode_row(row, encoding, make_excel_links=False))
126114
row_ctr += 1
127115

128-
yield xls_dataset(workbook).xls
129-
gc.collect()
116+
workbook.close()
117+
output.seek(0)
118+
yield output.getvalue()
130119
else:
131120
raise Exception("Unknown format: %s" % format)
132121

@@ -147,7 +136,7 @@ def make_response(generator, format, name, encoding=None, user_agent=None): # T
147136
pass
148137
elif format == 'xls':
149138
format = 'xlsx'
150-
resp = HttpResponse(next(generator), content_type=content_type)
139+
resp = StreamingHttpResponse(generator, content_type=content_type)
151140
elif format == 'json' or format == 'txt':
152141
resp = HttpResponse(generator, content_type=content_type)
153142
else:

0 commit comments

Comments
 (0)