vue+axios を使用してフロント エンドでファイルをアップロードし、express+fs を使用してサーバー サイドでファイルを受信および保存します。

フロントエンド

一般的なプロセスは次のとおりです。

  1. <input type="file"> タグのdom オブジェクトを取得するために、vue によって提供される ref 属性を使用します。
  2. dom オブジェクトのfiles 属性のデータ型は、入力ファイル情報であるFileListです。
  3. FileList をトラバースして File オブジェクトを取得し、FileReader を使用して File オブジェクトを読み取り、ファイルのArrayBuffer オブジェクトを取得します。(FileReader.readAsDataURL() を使用して、ファイルを base64 でエンコードされた URL 形式の文字列に変換し、次の手順を実行してバックエンドに渡すこともできます)
  4. ArrayBuffer オブジェクトを配列に変換し、ポスト リクエストを使用してバックエンドに送信します。(余談: ArrayBuffer オブジェクトを取得した場合、バックエンドはファイルを保存できますが、奇妙なことに、ArrayBuffer オブジェクトが post パラメータに直接挿入されている場合、バックエンドは空のオブジェクトを受け取りますが、ArrayBuffer が空オブジェクトではないので、ここではまず彼を配列に変換してから、その配列をバックエンドに送信します。)
<template>
  <label><input type="file" ref="input" multiple>文件</label>
  <button @click="submit">提交文件</button>
</template>

<script lang="ts" setup>
  import {
      
      ref} from 'vue'
  import axios from 'axios'
  const input = ref<any>()
  function submit(){
      
      
    const files = input.value.files as FileList
    for(let i = 0; i < files.length; i++){
      
      
      const file = files[i]
      const fileReader = new FileReader()
      fileReader.readAsArrayBuffer(file)
      //文件读取完毕触发onload事件
      
      fileReader.onload = () => {
      
      
        //把ArrayBuffer对象转换为数组
        const arrayBuffer = Array.from(new Uint8Array(fileReader.result as ArrayBuffer))
        axios.post('http://localhost:9000/submitFile', {
      
      fileName:file.name, arrayBuffer:arrayBuffer})
        .then(() => {
      
      console.log(file.name + '上传成功')})
      }
    }
  }
</script>

サーバ

サーバー側の処理は比較的シンプルです. 注目すべき点は2つあります. 1つは, bodyを解析するためのミドルウェアである body-parser のデフォルトのサイズ制限が100kbです. サイズが100kbを超えるとエラーが報告されます. fs.writeFile() の使用、その 2 番目のパラメーターは Buffer データ型を受け入れます、Buffer.from() の使用に注意してください、そのパラメーターは文字列、バッファー、配列、または arrayBuffer です。

const express = require('express')
const cors = require('cors')
const fs = require('fs')
const bodyParser = require('body-parser')
const app = express()

app.use(cors()) //允许简单请求和非简单请求的跨域

//解析Content-Type:application/x-www-form-urlencoded的body
app.use(bodyParser.urlencoded({
    
    
    extended: false,
    limit: '50mb' //body大小限制值,默认是100kb,但很多文件都大于100kb所以需要手动修改
}))

//解析Content-Type:application/json的body
app.use(bodyParser.json({
    
    limit: '50mb' })) //同理提高大小限制

const basePath = './' //规定保存文件的路径

app.post('/submitFile', (req, res) => {
    
    
    //把接收到的内容写入文件,Buffer.from()接收一个数组作为参数
    fs.writeFile(basePath + req.body.fileName, Buffer.from(req.body.arrayBuffer), error => {
    
    
        console.log(error)
    })
})
app.listen(9000)

より標準化されたファイルのアップロード

上記の方法は自分で手探りですが、基本的にはファイルオブジェクトを通してファイルデータを読み込み、ファイルデータを配列や文字列に変換し、最後にポストリクエストで渡します。
オンラインで検索したところ、そのようなファイルを転送する人はほとんどいません。また、オンラインのピクチャー ベッドやオブジェクト ストレージ クラウド サービスなどのサードパーティのクラウド ストレージ ライブラリを使用している場合、それらが提供する API はその種の転送方法をサポートしていません。

実際、ファイルをアップロードするより標準化された方法は、ファイル オブジェクトをポスト リクエスト パラメータの値として直接使用し、ファイル データを手動で読み取ったり処理したりせずに、ファイルをバックエンドに直接渡すことです。
ただ、以前やってみたところ、リクエストパラメータのファイルオブジェクトがブラウザキャプチャーで常に空のオブジェクトになっていたのですが、これはリクエストヘッダーが正しく設定されていないことが原因でした。ファイルのデータを正しくアップロードできるように、リクエストヘッダーをmultipart/form-dataに設定します。

フロントエンドは Content-Type=multipart/form-data を使用してファイルをアップロードします

リクエスト ヘッダーが異なることを除けば、他の通常のリクエスト手順とまったく同じです。ファイルのアップロード中に、一般的なタイプのパラメータをアップロードすることもできます.たとえば、次の例では、パラメータのフィールド名はファイル タイプで、名前は文字列タイプです.

//file是一个File对象
//name是一个字符串
//"fieldname"须和后端multer里的参数保持一致
axios.post('/upload', {
    
    "fieldname":file, "name":name})

バックエンド エクスプレスはミドルウェア multer を使用します

multer の基本的な使い方は次のとおりです。

const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors()) //允许简单请求和非简单请求的跨域

//引入multer
const multer = require("multer");

//在storage里定义文件的保存路径file.destination和文件名file.filename
//这里的req.body还未解析,为空。但req.query参数已解析,可用。这里的req.file为undefined
const storage = multer.diskStorage({
    
    

    destination: function (req, file, cb) {
    
    
        // console.log(req.body) 
        //cb函数设置保存路径,__dirname为当前文件所在目录
        cb(null, __dirname) 
    },

    filename: function (req, file, cb) {
    
    
        // console.log(req.body)   
        //获得文件名最后一个小数点的位置
        let indexOfPoint = file.originalname.lastIndexOf('.')
        //获得文件扩展名
        let fileExtention = file.originalname.slice(indexOfPoint)
        if(indexOfPoint === -1){
    
    
            fileExtention = ''
        }
        //文件名 = 时间戳 + 扩展名
        let filename = new Date().getTime() + fileExtention
        //cb函数设置filename
        cb(null, filename) 
    }
})


// 创建multer实例对象
const upload = multer({
    
     storage: storage});

//upload.single()参数是请求里面二进制对应的属性名,须和前端保持一致
app.post('/submitFile', upload.single("fieldname"), (req, res) => {
    
    
    //文件保存操作由multer在后台自动执行,我们无需关心。
    //在这里一般是向前端返回文件的保存信息,如文件名和文件保存位置,文件的url路径等。
    //file.originalname指文件的原始名字,file.filename是我们在上面storage中指定的名字
    res.end(JSON.stringify({
    
    name: req.file.filename, path: req.file.path}))
})

app.listen(9000)

おすすめ

転載: blog.csdn.net/m0_52744273/article/details/127408969