Add support for importing unzipped CSV
This commit is contained in:
parent
8e10bf3b16
commit
8a0a7a195e
|
@ -118,7 +118,7 @@ class TheFormDef extends React.PureComponent {
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
{...formItemLayout}
|
{...formItemLayout}
|
||||||
label="ZIP file">
|
label="CSV or ZIP file">
|
||||||
<div className="dropbox">
|
<div className="dropbox">
|
||||||
{getFieldDecorator("file", {
|
{getFieldDecorator("file", {
|
||||||
valuePropName: "file",
|
valuePropName: "file",
|
||||||
|
@ -129,11 +129,11 @@ class TheFormDef extends React.PureComponent {
|
||||||
multiple={ false }
|
multiple={ false }
|
||||||
fileList={ this.state.fileList }
|
fileList={ this.state.fileList }
|
||||||
beforeUpload={ this.onFileChange }
|
beforeUpload={ this.onFileChange }
|
||||||
accept=".zip">
|
accept=".zip,.csv">
|
||||||
<p className="ant-upload-drag-icon">
|
<p className="ant-upload-drag-icon">
|
||||||
<Icon type="inbox" />
|
<Icon type="inbox" />
|
||||||
</p>
|
</p>
|
||||||
<p className="ant-upload-text">Click or drag the ZIP file here</p>
|
<p className="ant-upload-text">Click or drag a CSV or ZIP file here</p>
|
||||||
</Upload.Dragger>
|
</Upload.Dragger>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -316,8 +316,8 @@ class Import extends React.PureComponent {
|
||||||
<hr />
|
<hr />
|
||||||
<div className="help">
|
<div className="help">
|
||||||
<h2>Instructions</h2>
|
<h2>Instructions</h2>
|
||||||
<p>Upload a ZIP file with a single CSV file in it
|
<p>Upload a CSV file or a ZIP file with a single CSV file in it
|
||||||
to bulk import a large number of subscribers in a single shot.
|
to bulk import a subscribers.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The CSV file should have the following headers with the exact column names
|
The CSV file should have the following headers with the exact column names
|
||||||
|
|
32
import.go
32
import.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/knadh/listmonk/subimporter"
|
"github.com/knadh/listmonk/subimporter"
|
||||||
"github.com/labstack/echo"
|
"github.com/labstack/echo"
|
||||||
|
@ -37,8 +38,7 @@ func handleImportSubscribers(c echo.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Mode != subimporter.ModeSubscribe && r.Mode != subimporter.ModeBlacklist {
|
if r.Mode != subimporter.ModeSubscribe && r.Mode != subimporter.ModeBlacklist {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest,
|
return echo.NewHTTPError(http.StatusBadRequest, "Invalid `mode`")
|
||||||
"Invalid `mode`")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.Delim) != 1 {
|
if len(r.Delim) != 1 {
|
||||||
|
@ -78,17 +78,25 @@ func handleImportSubscribers(c echo.Context) error {
|
||||||
}
|
}
|
||||||
go impSess.Start()
|
go impSess.Start()
|
||||||
|
|
||||||
// For now, we only extract 1 CSV from the ZIP. Handling async CSV
|
if strings.HasSuffix(strings.ToLower(file.Filename), ".csv") {
|
||||||
// imports is more trouble than it's worth.
|
go impSess.LoadCSV(out.Name(), rune(r.Delim[0]))
|
||||||
dir, files, err := impSess.ExtractZIP(out.Name(), 1)
|
} else {
|
||||||
if err != nil {
|
// Only 1 CSV from the ZIP is considered. If multiple files have
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError,
|
// to be processed, counting the net number of lines (to track progress),
|
||||||
fmt.Sprintf("Error extracting ZIP file: %v", err))
|
// keeping the global import state (failed / successful) etc. across
|
||||||
} else if len(files) == 0 {
|
// multiple files becomes complex. Instead, it's just easier for the
|
||||||
return echo.NewHTTPError(http.StatusBadRequest,
|
// end user to concat multiple CSVs (if there are multiple in the first)
|
||||||
"No CSV files found to import.")
|
// place and uploada as one in the first place.
|
||||||
|
dir, files, err := impSess.ExtractZIP(out.Name(), 1)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusInternalServerError,
|
||||||
|
fmt.Sprintf("Error extracting ZIP file: %v", err))
|
||||||
|
} else if len(files) == 0 {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest,
|
||||||
|
"No CSV files found to import.")
|
||||||
|
}
|
||||||
|
go impSess.LoadCSV(dir+"/"+files[0], rune(r.Delim[0]))
|
||||||
}
|
}
|
||||||
go impSess.LoadCSV(dir+"/"+files[0], rune(r.Delim[0]))
|
|
||||||
|
|
||||||
return c.JSON(http.StatusOK, okResp{app.Importer.GetStats()})
|
return c.JSON(http.StatusOK, okResp{app.Importer.GetStats()})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue