You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Node.js在浏览器打开PDF、DOCX文件?附Laravel文件预览代码解析

Hey there! Let's tackle your two questions step by step:

1. How to Open PDF & DOCX Files in Browser Using Node.js

Browsers handle PDFs natively, but DOCX needs extra work since there's no built-in support. Here are practical implementations:

For PDF Files

You can directly send the file with the correct Content-Type header, and browsers will render it inline. Using Express as an example:

const express = require('express');
const path = require('path');
const app = express();

// Route to preview PDF
app.get('/preview-pdf', (req, res) => {
  const pdfFilePath = path.join(__dirname, 'sample.pdf');
  // Set header to tell browser to preview instead of download
  res.setHeader('Content-Type', 'application/pdf');
  res.sendFile(pdfFilePath);
});

app.listen(3000, () => console.log('Server up on port 3000'));

For DOCX Files

Since browsers don't support DOCX preview out of the box, you have two main options:

Option 1: Convert DOCX to HTML (Server-Side)

Use mammoth.js to convert DOCX content to HTML, then send the HTML to the browser:

const express = require('express');
const mammoth = require('mammoth');
const fs = require('fs');
const path = require('path');
const app = express();

// Route to preview DOCX as HTML
app.get('/preview-docx', async (req, res) => {
  const docxFilePath = path.join(__dirname, 'sample.docx');
  
  try {
    const conversionResult = await mammoth.convertToHtml({ path: docxFilePath });
    // Wrap converted HTML in a basic page for better formatting
    const previewHtml = `
      <!DOCTYPE html>
      <html>
        <head>
          <title>DOCX Preview</title>
          <style>body { padding: 2rem; font-family: Arial; }</style>
        </head>
        <body>${conversionResult.value}</body>
      </html>
    `;
    res.setHeader('Content-Type', 'text/html');
    res.send(previewHtml);
  } catch (error) {
    console.error('DOCX conversion failed:', error);
    res.status(500).send('Could not preview DOCX file');
  }
});

app.listen(3000, () => console.log('Server running on port 3000'));

Option 2: Use Frontend Library to Render DOCX

Serve the DOCX file as a blob, then use a frontend library like docx-preview to render it:

Backend (Express)

app.get('/get-docx', (req, res) => {
  const docxFilePath = path.join(__dirname, 'sample.docx');
  res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
  res.sendFile(docxFilePath);
});

Frontend (HTML)

<!DOCTYPE html>
<html>
<head>
  <title>DOCX Preview</title>
  <script src="https://unpkg.com/docx-preview@0.1.17/dist/docx-preview.js"></script>
</head>
<body>
  <div id="docx-container" style="padding: 2rem;"></div>
  <script>
    // Fetch the DOCX file and render it
    fetch('/get-docx')
      .then(res => res.blob())
      .then(blob => {
        docx.renderAsync(blob, document.getElementById('docx-container'));
      });
  </script>
</body>
</html>
2. Laravel Code Breakdown

This snippet is a Laravel controller method that handles file preview based on MIME type, plus logs file access. Let's go line by line:

$doc = Document::findOrFail($id);
  • Uses Laravel's Eloquent ORM to fetch a Document record by ID. If no record exists, it automatically throws a 404 error (that's what findOrFail() does).
$path = Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix($doc->file);
  • Gets the full physical path of the file on the server. $doc->file is the relative path stored in the database; applyPathPrefix() adds the storage disk's base path (e.g., storage/app/ for the local disk) to get the absolute path.
$type = $doc->mimetype;
  • Pulls the file's MIME type (like application/pdf or application/vnd.openxmlformats-officedocument.wordprocessingml.document) from the database record.
Log::addToLog('Document ID '.$id.' à été consulté');
  • Logs that the document was accessed. The message is in French ("Document ID [X] has been viewed"). addToLog() is likely a custom logging method added to the project (Laravel's default uses Log::info()/Log::error() etc.).
if ($type == 'application/pdf' || $type == 'image/jpeg' || $type == 'image/png' || $type == 'image/jpg' || $type == 'image/gif') {
    return response()->file($path, ['Content-Type' => $type]);
} elseif ($type == 'video/mp4' || $type == 'audio/mpeg' || $type == 'audio/mp3' || $type == 'audio/x-m4a') {
    return view('documents.play',compact('doc'));
} else {
    return response()->file($path, ['Content-Type' => $type]);
}
  • First condition: For PDFs and common image types, it returns the file directly with the correct Content-Type header. Browsers will render these files inline (no download prompt).
  • Elseif condition: For audio/video files, it returns a dedicated view (documents.play) and passes the $doc data to it. This view probably includes an embedded player for media files.
  • Else block: For all other file types (like DOCX), it also returns the file directly. Note: Browsers can't preview these types natively, so this will usually trigger a download instead of inline preview.

A small optimization note: The response()->file() call is duplicated in the first and else blocks—you could refactor this to avoid repetition.


内容的提问来源于stack exchange,提问作者amine SGHIR

火山引擎 最新活动