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

Feature Request: Use MIME type checking to determine workbook file types #1750

Closed
davidjusto opened this issue Dec 11, 2023 · 8 comments
Closed

Comments

@davidjusto
Copy link

Description

I currently use plain UUIDs without any extension as filenames when handling workbooks. In 2.5.0 this works fine, as there is no file type check. As of 2.6.0, the library now checks for the correct file type - which is great - but since it uses the file extension for that, my use case breaks here.

I would propose a MIME type check in these methods:

if _, ok := supportedContentTypes[strings.ToLower(filepath.Ext(f.Path))]; !ok {

contentType, ok := supportedContentTypes[strings.ToLower(filepath.Ext(f.Path))]

Something like this:

var supportedMimeTypes = map[string]string{
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":    "",
  "application/vnd.ms-excel":                                             "",
  "application/vnd.ms-excel.sheet.macroEnabled.12":                       "",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.template": "",
  "application/vnd.ms-excel.template.macroEnabled.12":                    "",
}

mtype, err := mimetype.DetectFile(f.Path)
_, ok := supportedMimeTypes[mtype.String()]
if !ok {
  return ErrWorkbookFileFormat
}

This would use the mimetype package. Let me know what you think!

@davidjusto davidjusto changed the title Use MIME type checking to determine workbook file types Feature Request: Use MIME type checking to determine workbook file types Dec 11, 2023
@xuri
Copy link
Member

xuri commented Dec 12, 2023

Thanks for your issue. I suggest keeping this checking just like opening a workbook by spreadsheet application, it can't open a workbook without an extension name even if the file has a valid MIME type. But, you can use OpenReader function to open any file like this:

package main

import (
    "fmt"
    "os"

    "github.com/xuri/excelize/v2"
)

func main() {
    file, err := os.Open("UUID")
    if err != nil {
        return
    }
    f, err := excelize.OpenReader(file)
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()
    // ...
}

@davidjusto
Copy link
Author

Thanks for the quick answer, although my issue is not opening, it's the saving that doesn't work. Specifically the SaveAs and WriteTo methods.

I understand your reasoning why you don't want to use MIME. Maybe as a different approach, make the file type check optional?

@xuri
Copy link
Member

xuri commented Dec 12, 2023

Did you mean that the SaveAs and WriteTo don't work? Could you provide a demo or test case to reproduce that?

@davidjusto
Copy link
Author

davidjusto commented Dec 14, 2023

So just to be clear, there is no bug here. Just the change in behaviour from 2.5.0 to 2.6.0 (added file type check) breaks my use case.

A simple snippet that fails:

package main

import (
	"fmt"
	"github.com/xuri/excelize/v2"
)

func main() {
	f := excelize.NewFile()
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	index, err := f.NewSheet("Sheet2")
	if err != nil {
		fmt.Println(err)
		return
	}
	f.SetCellValue("Sheet2", "A2", "Hello world.")
	f.SetCellValue("Sheet1", "B2", 100)
	f.SetActiveSheet(index)

	if err := f.SaveAs("no-file-extension"); err != nil {
		fmt.Println(err)
	}
}

All my excel files are without file extension and I am opening them and editing them successfully with excelize. It's just the saving of those edited files that isn't allowed anymore.

@xuri
Copy link
Member

xuri commented Dec 14, 2023

Thanks for your feedback. Note that the Write function support write workbook to an io.Writer:

package main

import (
    "fmt"
    "os"

    "github.com/xuri/excelize/v2"
)

func main() {
    f := excelize.NewFile()
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()

    index, err := f.NewSheet("Sheet2")
    if err != nil {
        fmt.Println(err)
        return
    }
    f.SetCellValue("Sheet2", "A2", "Hello world.")
    f.SetCellValue("Sheet1", "B2", 100)
    f.SetActiveSheet(index)

    fi, err := os.Create("no-file-extension")
    if err != nil {
        fmt.Println(err)
        return
    }
    if err := f.Write(fi); err != nil {
        fmt.Println(err)
    }
    if err := fi.Close(); err != nil {
        fmt.Println(err)
    }
}

@davidjusto
Copy link
Author

davidjusto commented Dec 14, 2023

Thanks, that does indeed work for the use case of creating a new sheet, but I am opening an existing sheet like this:

package main

import (
	"fmt"
	"log"

	"github.com/xuri/excelize/v2"
)

func main() {
	// open works for files without specific extension
	f, err := excelize.OpenFile("test")
	if err != nil {
		log.Fatal(err)
	}

	defer func() {
		if err := f.Close(); err != nil {
			fmt.Println(err)
		}
	}()

	// manipulating file works
	index, err := f.NewSheet("Sheet2")
	if err != nil {
		fmt.Println(err)
		return
	}
	f.SetCellValue("Sheet2", "A2", "Hello world.")
	f.SetCellValue("Sheet1", "B2", 100)
	f.SetActiveSheet(index)

	// doesn't work
	// ErrWorkbookFileFormat
	err = f.Save()
        if err != nil {
              log.Fatal(err)
        }

	// will also not work
	// ErrWorkbookFileFormat
	/*
		fi, err := os.Create("no-file-extension")
		if err != nil {
			fmt.Println(err)
			return
		}
		defer fi.Close()

		if err := f.Write(fi); err != nil {
			log.Fatal(err)
		}
	*/
}

Here is the test excel file (zipped):
test.zip

Does that help to illustrate my issue with the type check?

@xuri
Copy link
Member

xuri commented Dec 15, 2023

Thanks for your information. There is an example for read and write workbook without file extension:

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/xuri/excelize/v2"
)

func main() {
    file, err := os.Open("test")
    if err != nil {
        fmt.Println(err)
        return
    }
    f, err := excelize.OpenReader(file)
    if err != nil {
        fmt.Println(err)
        return
    }
    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()

    defer func() {
        if err := f.Close(); err != nil {
            fmt.Println(err)
        }
    }()

    index, err := f.NewSheet("Sheet2")
    if err != nil {
        fmt.Println(err)
        return
    }
    f.SetCellValue("Sheet2", "A2", "Hello world.")
    f.SetCellValue("Tabelle1", "B2", 100)
    f.SetActiveSheet(index)

    fi, err := os.Create("test")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer fi.Close()

    if err := f.Write(fi); err != nil {
        log.Fatal(err)
    }
}

@xuri
Copy link
Member

xuri commented Jan 17, 2024

I've closed this. If you have any question, please let me know, and reopen this anytime.

@xuri xuri closed this as completed Jan 17, 2024
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

2 participants