← Back to Lessons Lesson 13 of 28
Intermediate api

File Processing

Introduction

File processing is an excellent Wasm use case — CPU-intensive parsing and transformation runs faster in Rust, and everything stays client-side (no server upload needed).

Reading Files from JavaScript

Users select files via <input type="file">, then pass the bytes to Rust:

const input = document.getElementById('file-input');
input.addEventListener('change', async (e) => {
    const file = e.target.files[0];
    const buffer = await file.arrayBuffer();
    const bytes = new Uint8Array(buffer);

    // Pass to Rust
    const result = process_file(bytes);
});

In Rust, accept &[u8]:

#[wasm_bindgen]
pub fn process_file(data: &[u8]) -> String {
    // data is a Uint8Array from JS
    format!("Received {} bytes", data.len())
}

CSV Processing

#[wasm_bindgen]
pub fn parse_csv(input: &str) -> JsValue {
    let mut records = Vec::new();

    for line in input.lines().skip(1) {  // skip header
        let fields: Vec<&str> = line.split(',').collect();
        records.push(fields);
    }

    // Convert to JS array
    serde_wasm_bindgen::to_value(&records).unwrap()
}

Image Processing

Process image pixels in Rust for speed:

#[wasm_bindgen]
pub fn grayscale(pixels: &mut [u8]) {
    // pixels is RGBA format: [r, g, b, a, r, g, b, a, ...]
    for chunk in pixels.chunks_exact_mut(4) {
        let gray = (0.299 * chunk[0] as f64
                  + 0.587 * chunk[1] as f64
                  + 0.114 * chunk[2] as f64) as u8;
        chunk[0] = gray;  // R
        chunk[1] = gray;  // G
        chunk[2] = gray;  // B
        // chunk[3] = alpha (unchanged)
    }
}
// Get image data from canvas
const imageData = ctx.getImageData(0, 0, width, height);
grayscale(imageData.data);  // Mutate in-place!
ctx.putImageData(imageData, 0, 0);

Generating File Downloads

Create files in Rust and trigger downloads from JavaScript:

#[wasm_bindgen]
pub fn generate_report() -> Vec<u8> {
    let csv = "name,score\nAlice,95\nBob,87\n";
    csv.as_bytes().to_vec()
}
const data = generate_report();
const blob = new Blob([data], { type: 'text/csv' });
const url = URL.createObjectURL(blob);

const a = document.createElement('a');
a.href = url;
a.download = 'report.csv';
a.click();
URL.revokeObjectURL(url);

Performance: Rust vs JavaScript

Operation JS Rust/Wasm
Parse 10MB CSV ~800ms ~150ms
Image grayscale (4K) ~50ms ~8ms
JSON parse (1MB) ~15ms ~5ms

Rust/Wasm wins significantly for data-intensive operations.

Try It

Click Run to see the CSV formatter in action. It parses comma-separated input and outputs an aligned table.

Try It

Chapter Quiz

Pass all questions to complete this lesson