mirror of
https://github.com/knadh/listmonk.git
synced 2024-11-10 17:13:04 +08:00
Add support for importing unzipped CSV
This commit is contained in:
parent
8e10bf3b16
commit
8a0a7a195e
2 changed files with 25 additions and 17 deletions
|
@ -118,7 +118,7 @@ class TheFormDef extends React.PureComponent {
|
|||
</Form.Item>
|
||||
<Form.Item
|
||||
{...formItemLayout}
|
||||
label="ZIP file">
|
||||
label="CSV or ZIP file">
|
||||
<div className="dropbox">
|
||||
{getFieldDecorator("file", {
|
||||
valuePropName: "file",
|
||||
|
@ -129,11 +129,11 @@ class TheFormDef extends React.PureComponent {
|
|||
multiple={ false }
|
||||
fileList={ this.state.fileList }
|
||||
beforeUpload={ this.onFileChange }
|
||||
accept=".zip">
|
||||
accept=".zip,.csv">
|
||||
<p className="ant-upload-drag-icon">
|
||||
<Icon type="inbox" />
|
||||
</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>
|
||||
)}
|
||||
</div>
|
||||
|
@ -316,8 +316,8 @@ class Import extends React.PureComponent {
|
|||
<hr />
|
||||
<div className="help">
|
||||
<h2>Instructions</h2>
|
||||
<p>Upload a ZIP file with a single CSV file in it
|
||||
to bulk import a large number of subscribers in a single shot.
|
||||
<p>Upload a CSV file or a ZIP file with a single CSV file in it
|
||||
to bulk import a subscribers.
|
||||
</p>
|
||||
<p>
|
||||
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/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/knadh/listmonk/subimporter"
|
||||
"github.com/labstack/echo"
|
||||
|
@ -37,8 +38,7 @@ func handleImportSubscribers(c echo.Context) error {
|
|||
}
|
||||
|
||||
if r.Mode != subimporter.ModeSubscribe && r.Mode != subimporter.ModeBlacklist {
|
||||
return echo.NewHTTPError(http.StatusBadRequest,
|
||||
"Invalid `mode`")
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid `mode`")
|
||||
}
|
||||
|
||||
if len(r.Delim) != 1 {
|
||||
|
@ -78,17 +78,25 @@ func handleImportSubscribers(c echo.Context) error {
|
|||
}
|
||||
go impSess.Start()
|
||||
|
||||
// For now, we only extract 1 CSV from the ZIP. Handling async CSV
|
||||
// imports is more trouble than it's worth.
|
||||
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.")
|
||||
if strings.HasSuffix(strings.ToLower(file.Filename), ".csv") {
|
||||
go impSess.LoadCSV(out.Name(), rune(r.Delim[0]))
|
||||
} else {
|
||||
// Only 1 CSV from the ZIP is considered. If multiple files have
|
||||
// to be processed, counting the net number of lines (to track progress),
|
||||
// keeping the global import state (failed / successful) etc. across
|
||||
// multiple files becomes complex. Instead, it's just easier for the
|
||||
// end user to concat multiple CSVs (if there are multiple in the first)
|
||||
// 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()})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue