Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] How can I send the xlxs file as a http response without actually creating the file? #148

Closed
cescoferraro opened this issue Nov 7, 2017 · 9 comments

Comments

@cescoferraro
Copy link

cescoferraro commented Nov 7, 2017

I want to create a GET endpoint where the user downloads the xlxs file created with excelize.
How can I achive such thing without actually creating a FS file. The below works, but its far from ideal.

func GenerateExcel(w http.ResponseWriter, r *http.Request) {
	xlsx := excelize.NewFile()
	xlsx.NewSheet(2, "Sheet2")
	xlsx.SetCellValue("Sheet2", "A2", "Hello world.")
	xlsx.SetCellValue("Sheet1", "B2", 100)
	xlsx.SetActiveSheet(2)
	err := xlsx.SaveAs("./Workbook.xlsx")
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
	data, err := ioutil.ReadFile("./Workbook.xlsx")
	if err != nil {
		log.Fatal(err)
	}
	w.Header().Set("Content-Type", "application/octet-stream")
	w.Header().Set("Content-Disposition", "attachment; filename="+"Workbook.xlsx")
	w.Header().Set("Content-Transfer-Encoding", "binary")
	w.Header().Set("Expires", "0")
	http.ServeContent(w, r, "Workbook.xlxs", time.Now(), bytes.NewReader(data))
}


@cescoferraro cescoferraro changed the title [Question] How can I send the xlxs file as a http response [Question] How can I send the xlxs file as a http response without actually creating the file? Nov 7, 2017
@xuri
Copy link
Member

xuri commented Nov 8, 2017

Thanks for your issue. http.ResponseWriter implements Write([]byte) (int, error), and the function Write provides function to write to an io.Writer.

func GenerateExcel(w http.ResponseWriter, r *http.Request) {
    xlsx := excelize.NewFile()
    xlsx.NewSheet("Sheet2")
    xlsx.SetCellValue("Sheet2", "A2", "Hello world.")
    xlsx.SetCellValue("Sheet1", "B2", 100)
    xlsx.SetActiveSheet(2)
    err := xlsx.SaveAs("./Workbook.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    w.Header().Set("Content-Type", "application/octet-stream")
    w.Header().Set("Content-Disposition", "attachment; filename="+"Workbook.xlsx")
    w.Header().Set("Content-Transfer-Encoding", "binary")
    w.Header().Set("Expires", "0")
    xlsx.Write(w)
}

@cescoferraro
Copy link
Author

@xuri Thanks! I off work today. Will try this asap. Do I still need to xlxs.SaveAs?

@cescoferraro
Copy link
Author

cescoferraro commented Nov 8, 2017

@xuri yeap that did it! There is no need to SaveAs, just Write(w) works. How about?

func (f *File) SendThroughHTTP(w http.ResponseWriter, filename string){
		w.Header().Set("Content-Type", "application/octet-stream")
		w.Header().Set("Content-Disposition", "attachment; filename="+filename+".xlsx")
		w.Header().Set("Content-Transfer-Encoding", "binary")
        f.Write(w)
}

@dolmen
Copy link
Contributor

dolmen commented Nov 15, 2017

@cescoferraro That would add an unnecessary dependency of excelize on net/http.

@sourabhkheterpal
Copy link

@cescoferraro : as you mentioned in above comment, we can achieve it without calling saveAs function.

I have executed the above code after removing saveAs function. When i did HTTP request it give me Response in Binary format.

func GenerateExcel(w http.ResponseWriter, r *http.Request) {
    xlsx := excelize.NewFile()
    xlsx.NewSheet("Sheet2")
    xlsx.SetCellValue("Sheet2", "A2", "Hello world.")
    xlsx.SetCellValue("Sheet1", "B2", 100)
    xlsx.SetActiveSheet(2)
  
    w.Header().Set("Content-Type", "application/octet-stream")
    w.Header().Set("Content-Disposition", "attachment; filename="+"Workbook.xlsx")
    w.Header().Set("Content-Transfer-Encoding", "binary")
    w.Header().Set("Expires", "0")
    xlsx.Write(w)
}

How can i save it as file with xlsx extension after making http request?

Please let me know if you need more detail.

@pulpfree
Copy link

When saving the file directly to disk with xlsx.SaveAs("./Workbook.xlsx") the file opens properly and all is good. However when writing to http.ResponseWriter as shown in @sourabhkheterpal's example, the file, when saved, isn't recognized and I cannot open it with an xlsx compatible application like Numbers.

Now I'm using the github.com/awslabs/aws-lambda-go-api-proxy/handlerfunc library which uses the base64.StdEncoding.EncodeToString method to encode the body. Am I right in assuming this encoding is the problem?

@zsr228
Copy link

zsr228 commented Jun 26, 2018

as you mentioned @xuri , use write function return file instream, the xlsx file downloaded , opening it isn't recognized and need to repair. can you tell me the problem?

@khawerrind
Copy link

Guys any solution for it?

@xuri
Copy link
Member

xuri commented Nov 5, 2018

@cescoferraro, @pulpfree, @zsspj12, @khawerrind The execlize now support to get bytes.Buffer from the saved file by WriteToBuffer(), and we can get io.Reader like this:

buf, _ := xlsx.WriteToBuffer()
strings.NewReader(buf.String())

Reference issue #127.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants