Download the PHP package kolay/xlsx-stream without Composer

On this page you can find all versions of the php package kolay/xlsx-stream. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package xlsx-stream

Kolay XLSX Stream

Latest Version on Packagist Tests Total Downloads License PHP Version

Bidirectional XLSX streaming for PHP and Laravel — and the only library in any language that makes the spreadsheet itself queryable. Write millions of rows straight to S3 with zero disk I/O, read them back with bounded memory, seek to any row in O(1), and ask for a column's sum, median, p99 or distinct count without reading a single row — over HTTP range requests, from a file Excel opens like any other.

Why this package?

Most PHP Excel libraries load whole documents into RAM (unusable at scale), spill temp files before uploading to S3, and can only read forward — reaching row 900,000 means scanning 899,999 rows first.

This package streams in both directions with constant memory, and its born-indexed mode embeds a small binary sidecar (xl/_kxs/index.bin) that vanilla readers ignore but this library uses for random access, block-pruned queries and sidecar-only analytics. Excel, LibreOffice, Numbers, PhpSpreadsheet and OpenSpout all open the files normally.

Performance

The trajectory — same canonical workloads, every release

v1.x (Sep 2025) v2.2 (May 2026) v3.0 (May 2026) v3.1 (Jul 2026) v3.2 (Jul 2026) v3.3 (Jul 2026)
Write, local ~182K rows/s ~210K ~215K ~289K ~289K ~289K
Write, S3 ~9K rows/s ~107K ~107K +36% same-link A/B + parallel window O(1) memory (was O(file))
Read, local ~70K rows/s ~106K ~127K ~127K
Random access O(1) rowAt + block-pruned queries + within-block skip (~19×) + bounded ranged fetch
Query engine columnStats/rowsWhere + groupStats AND / topRows / explain / by-name
Analytics 0-request sums median/p99/distinct 0-request + Bucket::month GROUP BY
Integrity verify() + S3 per-part checks
Peak RAM (write/read) 0-2 MB / — ~6 MB / — 6 / 24 MB 6 / 24 MB 6 / 6 MB 6 / 6 MB

Absolute S3 throughput tracks the network path far more than the library (the same 1M-row export measured 59K–153K rows/s across sessions) — the honest S3 claim is the same-day A/B: v3.2's writer is +36% over v3.0.2 on an identical link. Uploads are synchronous by default — part memory stays flat at ~part-size no matter how large the file, and throughput is steady; a parallel upload window is opt-in (concurrency) for high-latency links where hiding per-request round-trips outweighs its higher (sawtooth) memory. Benchmark on your own link.

Cross-package, 100K rows (May 2026, latest stables)

Write Time rows/s Read Time rows/s
kolay/xlsx-stream 0.65s 153K kolay/xlsx-stream 1.75s 57K
avadim/fast-excel-writer 5.23s 19K avadim/fast-excel-reader 4.60s 22K
openspout 5.77s 17K fast-excel 8.50s 12K
fast-excel 7.30s 14K openspout 9.90s 10K
phpspreadsheet 30.62s 3K phpspreadsheet 29.95s 3K

(Numbers predate the v3.1/v3.2 speedups. PhpSpreadsheet plays a different game — full Excel feature support at memory-bound cost.)

Every historical table (per-version scaling runs from 100 rows to 4.5M, random-access speedups, memory profiles, methodology) lives in BENCHMARK.md. All numbers come from the committed bench/ harnesses — fresh process per run, medians, generation cost subtracted; re-run them yourself.

File size limits

The writer emits ZIP32 archives. Each output is bounded by:

These ceilings are far above any realistic single-export workload (4.5 M rows ≈ 178 MB compressed). If a workload approaches them the writer aborts with a clear ZIP32 limit exceeded exception instead of silently truncating size fields and producing a corrupt file — split the export across multiple files or sheets as a workaround. ZIP64 writer support is tracked for a future release.

Compression level

setCompressionLevel(int $level) accepts 1–9. The default is 5 (v3.1+): measured on XLSX-shaped XML, level 5 produces a file within ~0.2 % of level 6's size at ~20 % less wall time — level 6 spends its extra effort on entropy (unique cell refs) that doesn't compress anyway. Pick by use case:

Use case Level Tradeoff
Queue job, fastest export 1 fastest, ~20 % larger file
Balanced default 5 knee of the size/speed curve for XLSX data
Marginally smaller 6 ~0.2 % smaller than 5, measurably slower
Archive, smallest file 9 much slower, ~6 % smaller file

For S3 uploads, a lower level typically wins because compute is the bottleneck. Level 9 only helps if you're storing the file long-term.

Comparison with Other Libraries

Package 1M Rows Write 1M Rows Read Memory (Read) Disk Usage Random Access S3 Support
PHPSpreadsheet ❌ Crashes ❌ Crashes ~8 GB Full file Indirect
Spout / OpenSpout ~60 sec ~30 sec ~100MB+ Full file Indirect
Laravel Excel ~90 sec ~60 sec ~500MB+ Full file Indirect
Kolay XLSX Stream (Local) 4.65 sec 14.30 sec 24 MB Zero O(1)* N/A
Kolay XLSX Stream (S3) 9.13 sec 16.60 sec 24 MB Zero O(1)* Direct

*With opt-in withRandomAccessIndex() on the writer. Per-lookup work is bounded by the writer-chosen sync period (default 10,000 rows), independent of file size. rowCount() is constant straight from the index header. Tune for latency-sensitive seeks with withRandomAccessIndex(every: 1000) or every: 100 for very dense random reads (file size grows ~1% per 10× density).

When to use this package vs alternatives

For most Laravel exports — use fast-excel. Simpler API, supports CSV/ODS, includes import functionality, battle-tested across millions of installs.

Use kolay/xlsx-stream when:

Use PhpSpreadsheet when:

Use OpenSpout when:

Requirements

Upgrading from v2.x? Reader and random-access APIs are purely additive — no breaking changes. See CHANGELOG.md for the full v3.2 highlights.

Upgrading from v1.x? See UPGRADE.md for the v2.0 migration guide as well.

Installation

Publish Configuration (Optional)

Use cases

Each scenario below links to the how-to section further down.

1. The million-row queued export that stopped eating RAM. A Laravel queue job streams FromQuery-style data straight to S3 — no temp file, no reopen-per-chunk, ~6 MB writer footprint, progress callbacks for the UI. Add withRandomAccessIndex() and the artifact is instantly seekable for every scenario below. → Direct S3 Streaming, Laravel Job Example, Progress Reporting.

2. "Download report" endpoints that start instantly. Stream the workbook into the HTTP response as it's generated (PhpStreamSinkphp://output) — first bytes reach the browser while row 1,000,000 is still being written. → Streaming directly to an HTTP response.

3. Importing customer uploads without fear. Read files produced by Excel/openpyxl/PhpSpreadsheet with bounded memory (shared-strings tables up to 64 MB compressed), correct dates via autoDetectDates(), validate row-by-row, and batch-insert. → Reading XLSX Files, Reading dates and times.

4. Parallel imports: wall clock = slowest worker. shards(8) splits a born-indexed sheet into eight independently decompressible, JSON-serializable ranges — dispatch one queue job per shard, zero coordination. → Parallel reads.

5. Admin file preview without importing to a database. Paginate a 4M-row S3 export in a UI: rowCount() is O(1), page 40,000 costs the same as page 1 via rowRange(), "jump to ID" is findRow() — two range requests on a sorted column. → Random-Access Reading.

6. Dashboard numbers straight from the file. "Total payroll", "median salary", "p99 order value", "distinct customers" — answered from the sidecar with zero row reads (columnStats, quantile, countDistinct), and per-month breakdowns via groupStats() reading only group-boundary blocks. The file IS the report backend. → Queryable XLSX, Grouped aggregates.

7. Styled corporate reports, still streaming. Header styling, per-row highlight styles, ₺/date/weekday number formats, frozen header, autofilter, auto column widths — all single-pass compatible. → Header & Column Styling.

8. Tight environments: Lambda, small pods, multi-tenant SaaS. Constant memory on both directions means the same code runs in a 128 MB function and a shared worker without per-tenant memory math.

Quick Start

Basic Usage - Local File

Direct S3 Streaming (Zero Disk I/O)

Reading XLSX Files (v3.0+)

The reader supports both files written by this package (zero indirection via inline strings) and files produced by other writers (PhpSpreadsheet, openpyxl, Apache POI, Excel itself) — the shared-strings table is loaded transparently when present.

Memory: Reader peak RAM is bounded — measured delta from baseline stays under 4 MB regardless of file size (CI-pinned via MemoryFootprintTest). The PHP runtime adds a ~20 MB baseline, so total RSS lands around 22-24 MB on real workloads.

Lifecycle: Reader resources are released automatically when the object goes out of scope (__destruct calls close()). For long-lived workers processing many files, calling $reader->close() or unset($reader) between iterations frees underlying handles eagerly.

Reading dates and times (v3.0+)

Excel stores dates as numeric serials (e.g. 46148 for 2026-05-06). The reader returns those as numeric strings by default — opt into automatic conversion per column:

Always use rows(skip: 1) with casts. Casts run on every row the generator yields, including row 1 (the header). A header string like "id" cast as 'int' returns null because is_numeric("id") is false. Read the header separately via $reader->header() (cast-free) and skip it on data iteration.

Timezone: Excel serials are timezone-naive. The reader returns datetimes in UTC by default so the same file produces the same result on every server regardless of date_default_timezone_get(). If your file's dates were authored in a specific timezone, set it explicitly:

Mac-origin Excel files using the 1904 epoch (rare): $reader->use1904Epoch();

Built-in cast names: date, datetime, int, float, bool. Pass any callable for custom transformations (parse to a value object, trim, normalise, etc.).

Streaming directly to an HTTP response (v3.0+)

Use PhpStreamSink::output() to stream a workbook into the active HTTP response — no temp file, constant memory, immediate first byte to the client. Pairs naturally with Laravel's Response::stream():

The sink also has temp() (in-memory until 2 MB, then a tmp file) and memory() (in-memory only) factories for capturing workbooks for later inspection — handy in tests.

Random-Access Reading (v3.0+)

Files written with withRandomAccessIndex() can be seeked into in O(1). The opt-in costs ~0.03 % file size and adds a single hidden ZIP part (xl/_kxs/index.bin) that vanilla XLSX readers ignore.

rowAt() and rowRange() work even on files without an index — they fall back to a sequential O(N) scan from the first row. Only the cost differs; the API contract is identical.

The physics of deflate streaming — seekability requires Z_FULL_FLUSH markers, and each marker resets the compressor's dictionary, which in principle costs compression ratio. In practice the cost is negligible at our default cadence: a sync point every 10K rows resets a 32 KB window once per ~1 MB of XML, measured at +0.04 % file size on the 500K-row benchmark workload (predicted ceiling ≤0.5 %). You would only notice dictionary-reset overhead at extreme settings like every: 100 — if you shrink the period for query granularity, re-measure your file sizes.

Performance tip: When you need many adjacent rows, prefer rowRange($from, $to) over a loop of rowAt() calls. rowRange() seeks once and reuses a single inflate stream; repeated rowAt() re-seeks on every call. For 1000 nearby rows the difference is ~1000× — a single ~ms seek versus 1000 × ms per call.

Queryable XLSX — zone maps & aggregates (v3.1+)

Born-indexed files can additionally carry per-block column statistics (min/max/sum/count for every ~10K-row block — the same idea as Parquet row-group stats, embedded in a plain .xlsx that Excel still opens normally). Track the columns you'll query when writing:

The reader then answers three kinds of questions without scanning row data:

Ops: =, <, <=, >, >=, between. Predicates match numeric cells (ints, floats, dates as serials); on files without stats the same calls degrade gracefully to a full-scan filter with identical results.

Grouped aggregates & approximate analytics (v3.2+)

Two more layers on the same sidecar:

The sketches are a merging t-digest (~1-4 KB/column, p01/p99 within 0.2% rank error) and a HyperLogLog (2 KB, ±5% pinned) per column — both merge associatively, which is what future segment/partition stitching builds on. The full binary layout is public: KXSI is an open spec (see SPEC.md) with committed conformance vectors under tests/SpecVectors/, so other implementations can verify byte-for-byte.

The query engine grows up (v3.3+)

The sidecar turns into a small SQL-shaped engine — all answered by reading only the blocks that can match, and all addressable by header name (not just 1-based index):

String lookups — find a record by code on S3 (v3.4+)

withStringStats([...]) adds per-block lexicographic zone maps (STRZ), so a string predicate prunes to the one block that can hold the value — a point lookup in a multi-GB S3 file in a couple of range requests:

Collation is unsigned UTF-8 byte order (= Unicode code-point order), the only sound basis for a streaming zone map — NOT locale. In Turkish, İ/ı sort by their bytes, not tr_TR rules; use this for exact / prefix / range lookups (codes, SKUs, IDs), not locale-correct sorting.

Data profiling & exact analytics (v3.4+)

The sidecar grows a profiling layer — a full per-column report, exact quantiles with a deterministic certificate, histograms, frequent values, and correlation — answered from the index cached at open, reading no data rows (profile() reads only the header once, bounded, to name columns):

Every number comes from the sidecar (zero row I/O), so it is not free of CPU — profile() runs each column's sketch math; "one range request" is a statement about I/O, not latency. A percentile's certificate width tracks row-order locality, not value clustering: a column sorted by (or covarying with) the sheet's order certifies tightly, a scattered one is honestly reported as [0, N]. The certificate resolution is bounded by the block size — on a sorted column its width is ≈ the sync interval (every), so it is a knob: a smaller every tightens the certificate and thins the exact-scan pruning, at the cost of a larger sidecar. histogram() also takes mode: 'depth' for equi-depth bins (each ≈ equal count), which reads a skewed column far better than the default equi-width. See SPEC.md §4–§6 for the format.

Integrity — verified reads & writes (v3.3+)

For data that matters (payroll, HR, audit exports):

Bigger, cheaper writes (v3.3+)

S3 writes are now O(1) memory. Multipart uploads default to synchronous (concurrency: 1): part memory stays flat at ~part-size no matter the file size. (Earlier versions defaulted to a parallel window that could grow memory toward the whole file.) Parallel is still an opt-in for high-latency links — see UPGRADE.md.

Parallel reads — shard a sheet across queue workers (v3.1+)

Every sync point in a born-indexed file is an independently decompressible boundary, so a sheet can be split into self-contained row ranges. The shard plan is plain JSON-friendly data — dispatch one queue job per shard and each worker streams only its slice, with zero coordination:

A 4M-row import's wall clock becomes max(worker time) instead of the sum. Shard boundaries snap to sync points (balanced to within one sync period); on non-indexed files shards() returns a single whole-sheet shard — same contract, no parallelism.

Laravel Job Example

Advanced Features

Laravel Storage Disk Integration (v2.1+)

Skip the manual S3Client setup — forDisk() reads everything from config('filesystems.disks.{$disk}'):

Streaming from Eloquent with lazy() (v2.1+)

writeRows() accepts any iterable — pass an Eloquent lazy() cursor for constant-memory streaming over millions of rows:

Generators work too:

Progress Reporting for Queue Jobs (v2.1+)

Register a callback that fires every N rows with (rows, bytes). Zero overhead when not used:

Note on $bytes — the byte counter only advances when zlib emits compressed output. With small datasets (or when setBufferFlushInterval() is large relative to setProgressInterval()), several events in a row may report the same byte count between flushes. The row counter is always exact; if you need accurate streamed-byte progress on small files, lower setBufferFlushInterval() below your progress interval.

Supported Cell Data Types

The writer infers the right Excel cell type from each PHP value:

PHP value Excel cell
int, float numeric (t="n")
bool native boolean (t="b") — 1 for true, 0 for false
\DateTimeInterface (DateTime, DateTimeImmutable, Carbon, …) numeric serial date with yyyy-mm-dd hh:mm:ss format — sortable as a date in Excel
numeric string ≤ 15 digits numeric (t="n")
numeric string > 15 digits, leading-zero ("00123"), or +-prefixed inline string — preserves precision and formatting
null or '' empty cell
anything else inline string (t="inlineStr")

Header & Column Styling (v2.2+)

A small set of opt-in styling APIs that costs ~2-3% throughput and adds ~3% to the file size. Skip them and the writer takes the v1.x-equivalent hot path.

Available format presets: date, datetime, datetime_iso, time, integer, decimal, percent, currency_try, currency_usd, currency_eur, currency_gbp. Pass any other string to use a raw Excel format code (e.g. 0.000, #,##0.00 "kg").

setAutoColumnWidth() derives a width from the header text length but also respects a per-format minimum so a currency_try column with the header Salary won't render as ####. Override per column with setColumnWidths([1 => 8, 2 => 30]) when you want exact control.

Template mode — stream into someone else's layout (v3.5+)

The expensive part of an .xlsx is not its layout, it is its rows. Template mode takes the layout from a workbook another producer authored — Excel, PhpSpreadsheet, or this package — and streams only the rows into it. The sheet is cut once at <sheetData>; everything else in the archive is moved across without being inflated.

The template doubles as a style oracle. The rows below dataStartRow are sample rows, one per look you want, and they are read rather than written: their s="…" ids tell the writer how that producer encoded each style, so nothing has to be re-specified here.

writeRows() takes the same choice as a callback:

What the template owns, and what this writer will therefore refuse: the header rows and their styles, column widths, freeze panes, the auto filter, per-column number formats, and the style table itself. Calling startFile(), newSheet(), compact(), setHeaderStyle(), setColumnWidths(), setAutoColumnWidth(), freezeFirstRow(), enableAutoFilter(), setColumnFormat() or registerRowStyle() in template mode throws, rather than half-applying over a layout that already decided. A row's look comes from its variant, so passing a registered style id to writeRow() throws too — one argument, one meaning.

Writing a template. Author it in Excel or PhpSpreadsheet, put one sample row per style variant below the header, and keep every range in the sheet above the data:

Identity numbers stay text. A numeric-looking string is written as a number unless precision would be lost — a leading zero, a leading plus, or more than fifteen digits. A national identity number, a tax number or an account number sits inside that window, so it would otherwise land as a right-aligned number. Declare those columns:

Columns are 1-based. The declaration governs string values, so an int stays an int — pass the identifier as a string when you want it as text. It applies to the sheet chosen by the last sheet() call, and the next sheet() clears it.

Number formats. Where the template holds an opinion it wins outright, including for dates: a DateTimeInterface written into a column the sample row styled takes that column's format, not this package's default. Past the sample row's last styled cell the template says nothing, so the classic date format applies and is appended to the style table on first use.

Text cells join the template's xl/sharedStrings.xml when it has one, which is what PhpSpreadsheet expects on the way back in. A template without that part gets inline strings instead. The dictionary is the one place this mode holds memory proportional to the data, so it has a ceiling:

Past the ceiling new strings are written inline, so the file stays valid and memory stops growing.

Random access works on the streamed sheet: withRandomAccessIndex() and the analytics opt-ins behave exactly as they do for a classic write, and the sidecar's content type is declared in the template's [Content_Types].xml. Sheets carried across untouched are not described by the sidecar; the reader answers from them by scanning.

Header addressing. The reader treats physical row 1 as the header. If a template's first row is a merged report title rather than column names, address columns by index (profile([2]), rowsWhere(2, …)) instead of by name.

When not to use it. Template mode covers a layout that is fixed before the data arrives. A merge whose row span is only known while streaming is not covered — that is first-class writer styling, and it is on the roadmap for v3.6.

Templates from PhpSpreadsheet 1.x and 5.x are both covered by the parity suite, which runs against each major on tag day.

Measured on a real 8,000 × 10 report against building the same file with PhpSpreadsheet: 17× faster, 14× less memory. A different workload gives a different ratio — PhpSpreadsheet's per-row style cost is not linear — so BENCHMARK.md §5 reports each number with the workload it was measured on, alongside the parity result: 400 rows × 6 columns compared against PhpSpreadsheet's own output on 12 properties, zero differences.

Manual Multi-Sheet Workbooks (v2.2+)

newSheet($name, $headers = null) carves a workbook into named domain sheets — orthogonal to the auto-split fallback at 1,048,576 rows.

clearColumnFormats() is the convenient way to drop the previous sheet's per-column registrations before starting a new one with a different column layout.

Multi-Sheet Support (Automatic)

The writer automatically creates new sheets when reaching Excel's row limit (1,048,576 rows):

Reading auto-split files back (v3.2.2+): on born-indexed files the reader detects the continuation chain (consecutive exactly-full sheets with identical headers) and treats it as ONE logical table — rowCount(), rowsWhere(), findRow(), columnStats(), quantile(), shards() and friends span every continuation sheet with continuous global row numbers. Intentional multi-sheet workbooks (different headers, or sheets that aren't exactly full) keep per-sheet semantics. Before v3.2.2 queries silently answered from the active sheet alone — treat that as a reason to upgrade if you export past one sheet.

Measured on a 2.1M-row, 3-sheet chain (local disk, 6 MB peak RAM): chain detection + rowCount() 1.5 ms on first call (~1 µs warmed), findRow() into the second sheet 9.5 ms, rowAt() 2.2 ms, columnStats() 1.5 ms, quantile() 1.7 ms. Single-sheet files take an early-out before any chain logic — the A/B benchmark against v3.2.1 shows every single-sheet read path within ±1 % (measurement noise).

Performance Tuning

Custom S3 Parameters

Error Handling

Configuration

Defaults come from the published config file; code-level setters always override them at call time. (Fixed in v3.2.2 — earlier releases shipped these keys without reading them; re-publish the config to opt in: php artisan vendor:publish --tag=xlsx-stream-config --force. The new file carries a 'version' => 2 marker; pre-3.2.2 copies stay inert so their stale defaults can't silently change your output.)

Transient S3 retries belong to the AWS SDK — configure them on your S3Client ('retries' => N); the sink adds one last-resort re-dispatch after the SDK gives up. Progress/"logging" is the onProgress() callback: wire it to your logger of choice.

How It Works

The Architecture

The Magic Behind Zero Disk I/O

  1. Binary XLSX Generation

    • XLSX files are ZIP archives containing XML files
    • We generate ZIP structure directly in memory
    • No intermediate files or DOM tree building
  2. Streaming Compression

    • Data is compressed using PHP's deflate_add() in chunks
    • Each row is immediately compressed and streamed
    • No need to store uncompressed data
  3. Smart Buffering

    • Configurable row buffer (default 10,000 rows)
    • Flushes periodically to maintain streaming
    • Prevents memory accumulation
  4. S3 Multipart Upload
    • Direct streaming to S3 using multipart upload
    • Default 8 MB parts, uploaded synchronously and released as they land (O(1) memory); parallel uploads are opt-in
    • No local file required at any point

Memory model

The random-access / query layer is built on deflate FULL_FLUSH sync points plus the KXSI sidecar — the full binary format, its invariants and the conformance suite are documented in SPEC.md.

Real-World Performance

Production Test Results (4.5 Million Rows)

Our production systems successfully export massive datasets daily:

Key Performance Metrics (v3.3)

Compatibility

The optional xl/_kxs/index.bin sidecar emitted by withRandomAccessIndex() is declared as application/octet-stream in [Content_Types].xml, so editors that don't recognise it leave the file alone instead of flagging it for repair.

Files produced by the v3.0 writer (both with and without the sidecar) open cleanly without repair mode in:

If a downstream editor strips or rewrites the sheet, the next indexed read silently falls back to a sequential scan via the embedded sheet CRC32 cross-check — same end result, just without the O(1) speedup. The reader-side fallback is verified by tests/Writers/RandomAccessIndexWriterTest.php.

v3.1/v3.2 extend the same sidecar with additional TLV sections (STAT/SCRC/TDIG/CHLL) under the identical opaque-part contract; manual open-tests are repeated against real Excel before every tag.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Testing

License

The MIT License (MIT). Please see License File for more information.

Credits

Support

For issues and questions, please use the GitHub issue tracker.


All versions of xlsx-stream with dependencies

PHP Build Version
Package Version
Requires php Version ^8.1
ext-zlib Version *
ext-hash Version *
illuminate/support Version ^10.0|^11.0|^12.0|^13.0
aws/aws-sdk-php Version ^3.180
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package kolay/xlsx-stream contains the following files

Loading the files please wait ...