使用Golang上传PDF文件到phpMyAdmin的方法

使用Golang上传PDF文件到phpMyAdmin的方法 我使用MVC结构编写代码,并构建了将PDF文件上传到数据库(phpmyadmin)的功能,但我无法将文件上传到我的数据库。

2 回复

在没有看到任何代码的情况下,这个问题将极难诊断。

将PDF上传到MySQL数据库必须作为BLOB(二进制大对象)来处理。然而,这会使你的数据库体积迅速膨胀。如果你追求性能,更好的做法可能是将PDF上传到文件系统。Stack Overflow上的这篇帖子可能对你的情况很有帮助:Stack Overflow MySQL Blob。不过,他们帖子中引用的链接已经失效,你可以在这里找到相关内容:Storage Sizes Blob

更多关于使用Golang上传PDF文件到phpMyAdmin的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Golang中通过MVC架构上传PDF文件到MySQL数据库(phpMyAdmin是管理界面),需要处理文件上传、数据库存储两个关键环节。以下是完整的实现示例:

1. 模型层(Model) - 数据库结构

首先创建存储PDF文件的数据库表:

CREATE TABLE pdf_documents (
    id INT AUTO_INCREMENT PRIMARY KEY,
    filename VARCHAR(255) NOT NULL,
    file_size INT NOT NULL,
    content LONGBLOB NOT NULL,
    uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

2. 模型层(Model) - Go结构体

// models/document.go
package models

import (
    "database/sql"
    "time"
)

type PDFDocument struct {
    ID         int       `json:"id"`
    Filename   string    `json:"filename"`
    FileSize   int64     `json:"file_size"`
    Content    []byte    `json:"-"`
    UploadedAt time.Time `json:"uploaded_at"`
}

type DocumentModel struct {
    DB *sql.DB
}

func (m *DocumentModel) Insert(doc *PDFDocument) (int, error) {
    query := `INSERT INTO pdf_documents (filename, file_size, content) 
              VALUES (?, ?, ?)`
    
    result, err := m.DB.Exec(query, doc.Filename, doc.FileSize, doc.Content)
    if err != nil {
        return 0, err
    }
    
    id, err := result.LastInsertId()
    if err != nil {
        return 0, err
    }
    
    return int(id), nil
}

func (m *DocumentModel) GetByID(id int) (*PDFDocument, error) {
    query := `SELECT id, filename, file_size, content, uploaded_at 
              FROM pdf_documents WHERE id = ?`
    
    row := m.DB.QueryRow(query, id)
    
    doc := &PDFDocument{}
    err := row.Scan(&doc.ID, &doc.Filename, &doc.FileSize, &doc.Content, &doc.UploadedAt)
    if err != nil {
        return nil, err
    }
    
    return doc, nil
}

3. 控制器层(Controller)

// controllers/document_controller.go
package controllers

import (
    "io"
    "net/http"
    "path/filepath"
    "strconv"
    "your-app/models"
)

type DocumentController struct {
    DocumentModel *models.DocumentModel
}

func (c *DocumentController) UploadPDF(w http.ResponseWriter, r *http.Request) {
    // 限制上传大小(例如10MB)
    r.ParseMultipartForm(10 << 20)
    
    // 获取上传的文件
    file, handler, err := r.FormFile("pdfFile")
    if err != nil {
        http.Error(w, "无法获取上传的文件: "+err.Error(), http.StatusBadRequest)
        return
    }
    defer file.Close()
    
    // 验证文件类型
    if filepath.Ext(handler.Filename) != ".pdf" {
        http.Error(w, "只允许上传PDF文件", http.StatusBadRequest)
        return
    }
    
    // 读取文件内容
    fileBytes, err := io.ReadAll(file)
    if err != nil {
        http.Error(w, "读取文件失败: "+err.Error(), http.StatusInternalServerError)
        return
    }
    
    // 创建文档对象
    doc := &models.PDFDocument{
        Filename: handler.Filename,
        FileSize: handler.Size,
        Content:  fileBytes,
    }
    
    // 保存到数据库
    id, err := c.DocumentModel.Insert(doc)
    if err != nil {
        http.Error(w, "保存到数据库失败: "+err.Error(), http.StatusInternalServerError)
        return
    }
    
    w.WriteHeader(http.StatusCreated)
    w.Write([]byte("文件上传成功,ID: " + strconv.Itoa(id)))
}

func (c *DocumentController) DownloadPDF(w http.ResponseWriter, r *http.Request) {
    // 从URL参数获取文档ID
    idStr := r.URL.Query().Get("id")
    id, err := strconv.Atoi(idStr)
    if err != nil {
        http.Error(w, "无效的ID", http.StatusBadRequest)
        return
    }
    
    // 从数据库获取文档
    doc, err := c.DocumentModel.GetByID(id)
    if err != nil {
        http.Error(w, "文档不存在", http.StatusNotFound)
        return
    }
    
    // 设置响应头
    w.Header().Set("Content-Type", "application/pdf")
    w.Header().Set("Content-Disposition", "attachment; filename="+doc.Filename)
    w.Header().Set("Content-Length", strconv.FormatInt(doc.FileSize, 10))
    
    // 写入PDF内容
    w.Write(doc.Content)
}

4. 路由层(Router)

// main.go
package main

import (
    "database/sql"
    "log"
    "net/http"
    "your-app/controllers"
    "your-app/models"
    
    _ "github.com/go-sql-driver/mysql"
)

func main() {
    // 连接MySQL数据库
    dsn := "username:password@tcp(localhost:3306)/database_name?parseTime=true"
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 初始化模型
    docModel := &models.DocumentModel{DB: db}
    
    // 初始化控制器
    docController := &controllers.DocumentController{
        DocumentModel: docModel,
    }
    
    // 设置路由
    http.HandleFunc("/upload", docController.UploadPDF)
    http.HandleFunc("/download", docController.DownloadPDF)
    
    // 启动服务器
    log.Println("服务器启动在 :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

5. 前端HTML表单

<!-- upload.html -->
<!DOCTYPE html>
<html>
<head>
    <title>上传PDF文件</title>
</head>
<body>
    <h1>上传PDF到数据库</h1>
    <form action="/upload" method="POST" enctype="multipart/form-data">
        <input type="file" name="pdfFile" accept=".pdf" required>
        <button type="submit">上传</button>
    </form>
</body>
</html>

6. 依赖安装

go get github.com/go-sql-driver/mysql

关键注意事项:

  1. 数据库连接:确保MySQL连接字符串正确,数据库用户有足够的权限
  2. 文件大小限制:代码中设置了10MB限制,可根据需要调整
  3. 内存使用:大文件上传时考虑使用流式处理
  4. 安全性:实际部署时应添加文件类型验证、用户认证等安全措施

这个实现通过LONGBLOB类型在MySQL中存储PDF二进制数据,phpMyAdmin可以正常显示和管理这些记录。

回到顶部