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

Check browser support #4

Closed
Siemienik opened this issue Apr 14, 2020 · 8 comments
Closed

Check browser support #4

Siemienik opened this issue Apr 14, 2020 · 8 comments

Comments

@Siemienik
Copy link
Owner

No description provided.

@Siemienik Siemienik mentioned this issue Oct 14, 2020
7 tasks
@Metastasis
Copy link
Contributor

Metastasis commented Oct 17, 2020

@Siemienik
I see that you already created issue for browser support so I write here what I found while working on #6

Under the hood you're using exceljs which supports 3 types of importing: from a file, from a stream, from a buffer.

ImporterFactory currently supports importing from a file. This is not going to work in browsers due to security reasons. I think there's no way to extract file path from uploaded files (uploaded with input type file).

Therefore I have proposal. In exceljs docs you can find section called "Browser" which points you to this test file. Basically they're using Buffer (node js) or similar concept ArrayBuffer for browsers. So I think we can use FileReader in order to support browsers. Particulary method readAsArrayBuffer. It has good browser support. FileReader too.

My proposal

  1. Add load method from exceljs which reads excel file from Buffer. I think I can add it here. Something like this
    public async from(path: string | ArrayBuffer | Buffer): Promise<IImporter> {
        const wb = new Workbook();
        if (typeof path === 'string') {
            await wb.xlsx.readFile(path);
        } else {
            await wb.xlsx.load(path);
        }

        return new Importer(wb);
    }
  1. Then we can use it in browsers like this
const factory = new ImporterFactory();

export const importInvoice = async (buffer: ArrayBuffer): Promise<IInvoice> => {
  // ...import invoice here
};

function App() {
  const [invoice, setInvoice] = useState<IInvoice | null>(null);
  const onUpload = useCallback((event) => {
    const invoiceFile = event.target.files[0];
    const reader = new FileReader();
    reader.readAsArrayBuffer(invoiceFile);
    reader.addEventListener('loadend', (e) => {
      if (reader.result instanceof ArrayBuffer) {
        importInvoice(reader.result).then(setInvoice);
      }
    })
  }, []);
  return (
    <div className="App">
      {/* ...render invoice here */}
    </div>
  );
}

UPD:
After I write this comment I realized that string can also be a buffer so probably my implementation is broken (string can represent buffer as well as file path). I need to think about this

UPD2:
I think implementation is ok since load method has following signature

@Siemienik
Copy link
Owner Author

Siemienik commented Oct 17, 2020

@Siemienik
I see that you already created issue for browser support so I write here what I found while working on #6

Thank you, for extensive research 👍

it will be fine to handle data url and fetching from url (for instance https://example.com/some-invoice.xlsx) also.
I consider about write issues for each type of input. @Metastasis WDYT?

Then this issue will be fulfilled by checking if this works:

import {Importer} from 'xlsx-import/lib/Importer';

function App() {
  const [invoice, setInvoice] = useState<IInvoice | null>(null);
  const onUpload = useCallback((event) => {
    const invoiceFile = event.target.files[0];
    const reader = new FileReader();
    reader.readAsArrayBuffer(invoiceFile);
    reader.addEventListener('loadend', (e) => {
      if (reader.result instanceof ArrayBuffer) {
            const wb = new Workbook();
            await wb.xlsx.load(reader.result);
            const importer = new Importer(wb);
            const seller = importer.getAllItems(sellerCfg)[0];
 
           // ...

      }
    })
  }, []);
  return (
    <div className="App">
      {/* ...render invoice here */}
    </div>
  );
}

I mean it will be great to prove it by at least one selenium (or cypress) test runned under Chrome and Firefox

@Metastasis
Copy link
Contributor

Metastasis commented Oct 17, 2020

@Siemienik
So is it correct that I should

  1. Fetch file from https://example.com/some-invoice.xlsx (Blob will be returned)
  2. Read Blob with FileReader and get ArrayBuffer
  3. Pass ArrayBuffer to ImportFactory
  4. Import invoice file
  5. Render result
  6. ???
  7. Profit

@Siemienik
Copy link
Owner Author

AD3. In scope of this issue I think is enough to create Importer without using ImportFactory. That allows us do not care about ImportFactory interface and focus on checking if it works with browsers.

(I'm going to create new issue for ImportFactory api)

AD6. Using selenium to assert that result is right

AD7. Profit - we have proved by test that our lib working with browsers, thats enable us to work further with browsers features

P.S. I'm afraid about same problem like here: https://github.com/Siemienik/xlsx-renderer/issues/13#issuecomment-704589977
(excelJs issue: exceljs/exceljs#1492)

@Metastasis
Copy link
Contributor

Metastasis commented Oct 18, 2020

@Siemienik
Got it, thanks 👍
I think we should update samples in future after ImportFactory issue will be resolved in order to show "the right way"

@Siemienik
Copy link
Owner Author

@Metastasis I created #52, could you check if I've nothing forget?

I think we should update samples in future after ImportFactory issue will be resolved in order to show "the right way"

Fully agree!

@Siemienik
Copy link
Owner Author

#57 prove that xlsx-import may works on browsers, I'm really happy of that 💯

@Siemienik
Copy link
Owner Author

In samples/vue and samples/react was proved browser support.
#65 introduces CI for regularly checking browser support.

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