summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLijingfeng <170574@qq.com>2020-10-05 22:17:11 +0800
committerGitHub <noreply@github.com>2020-10-05 22:17:11 +0800
commit93160287bb7fa6479c73ee031b5ed771972a17a8 (patch)
treeb875bf60a7eb30a83ea233b52e5740609dda4f5a
parentf2b8798a34aab4411a50861a4cdf47203edc3a19 (diff)
Optimize memory usage when stream flush and save (#659)
* use io.Copy from stream temp file to zip Writer * fix nil * log * build * delete log * fix compatibility for office * Update go module Co-authored-by: lijingfeng <lijingfeng@laiye.com> Co-authored-by: xuri <xuri.me@gmail.com>
-rw-r--r--excelize.go1
-rw-r--r--file.go20
-rw-r--r--go.mod2
-rw-r--r--stream.go44
4 files changed, 30 insertions, 37 deletions
diff --git a/excelize.go b/excelize.go
index cca6616..0c0f74a 100644
--- a/excelize.go
+++ b/excelize.go
@@ -36,6 +36,7 @@ type File struct {
xmlAttr map[string][]xml.Attr
checked map[string]bool
sheetMap map[string]string
+ streams map[string]*StreamWriter
CalcChain *xlsxCalcChain
Comments map[string]*xlsxComments
ContentTypes *xlsxTypes
diff --git a/file.go b/file.go
index 6a48c0c..4a2ab10 100644
--- a/file.go
+++ b/file.go
@@ -110,6 +110,26 @@ func (f *File) WriteToBuffer() (*bytes.Buffer, error) {
f.sharedStringsWriter()
f.styleSheetWriter()
+ for path, stream := range f.streams {
+ fi, err := zw.Create(path)
+ if err != nil {
+ zw.Close()
+ return buf, err
+ }
+ var from io.Reader
+ from, err = stream.rawData.Reader()
+ if err != nil {
+ stream.rawData.Close()
+ return buf, err
+ }
+ _, err = io.Copy(fi, from)
+ if err != nil {
+ zw.Close()
+ return buf, err
+ }
+ stream.rawData.Close()
+ }
+
for path, content := range f.XLSX {
fi, err := zw.Create(path)
if err != nil {
diff --git a/go.mod b/go.mod
index fb2c1e8..4b6e778 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/360EntSecGroup-Skylar/excelize/v2
-go 1.15
+go 1.11
require (
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
diff --git a/stream.go b/stream.go
index 83b25f7..bbb1ec1 100644
--- a/stream.go
+++ b/stream.go
@@ -85,6 +85,13 @@ func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {
if err != nil {
return nil, err
}
+
+ sheetXML := fmt.Sprintf("xl/worksheets/sheet%d.xml", sw.SheetID)
+ if f.streams == nil {
+ f.streams = make(map[string]*StreamWriter)
+ }
+ f.streams[sheetXML] = sw
+
sw.rawData.WriteString(XMLHeader + `<worksheet` + templateNamespaceIDMap)
bulkAppendFields(&sw.rawData, sw.worksheet, 2, 6)
sw.rawData.WriteString(`<sheetData>`)
@@ -387,13 +394,8 @@ func (sw *StreamWriter) Flush() error {
sheetXML := fmt.Sprintf("xl/worksheets/sheet%d.xml", sw.SheetID)
delete(sw.File.Sheet, sheetXML)
delete(sw.File.checked, sheetXML)
+ delete(sw.File.XLSX, sheetXML)
- defer sw.rawData.Close()
- b, err := sw.rawData.Bytes()
- if err != nil {
- return err
- }
- sw.File.XLSX[sheetXML] = b
return nil
}
@@ -444,36 +446,6 @@ func (bw *bufferedWriter) Reader() (io.Reader, error) {
return io.NewSectionReader(bw.tmp, 0, fi.Size()), nil
}
-// Bytes returns the entire content of the bufferedWriter. If a temp file is
-// used, Bytes will efficiently allocate a buffer to prevent re-allocations.
-func (bw *bufferedWriter) Bytes() ([]byte, error) {
- if bw.tmp == nil {
- return bw.buf.Bytes(), nil
- }
-
- if err := bw.Flush(); err != nil {
- return nil, err
- }
-
- var buf bytes.Buffer
- if fi, err := bw.tmp.Stat(); err == nil {
- if size := fi.Size() + bytes.MinRead; size > bytes.MinRead {
- if int64(int(size)) == size {
- buf.Grow(int(size))
- } else {
- return nil, bytes.ErrTooLarge
- }
- }
- }
-
- if _, err := bw.tmp.Seek(0, 0); err != nil {
- return nil, err
- }
-
- _, err := buf.ReadFrom(bw.tmp)
- return buf.Bytes(), err
-}
-
// Sync will write the in-memory buffer to a temp file, if the in-memory
// buffer has grown large enough. Any error will be returned.
func (bw *bufferedWriter) Sync() (err error) {