文件上传基础上传

226 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情

文件上传格式

前后端数据传输一般有以下格式 formData x-www-form-urlencoded json 普通文本字符串 Buffer

但是文件上传一般都是formData也可以是buffer

demo

  const fm = new FormData()
  fm.append('key', 'value'),
    fm.append(filename, file)
  return axios.post('http://127.0.0.1:8888/upload_single', fm, {
    headers: {
      "Content-Type": "mutipart/form-data"
    }
  })

文件类型 axios 封装

如果大多情况下上传的都是文件类型,那么axios默认的header就设置成 "Content-Type": "mutipart/form-data"。 如果有urlencoded形式传的参数,就在请求拦截器里统一使用qs将josn转换成urlencoded格式。

import axios from 'axios'
import Qs from 'qs'
const urlencodedHeader = {
  "Content-Type": "application/x-www-form-urlencoded"
}
const uploadHttp = axios.create({
  baseURL: "http://127.0.0.1:8888",
  timeout: 5000,
  headers: {
    "Content-Type": "mutipart/form-data"
  },
  transformRequest (data, headers) {
    const contentType = headers['Content-Type']
    if (contentType === urlencodedHeader['Content-Type']) {
      return Qs.stringify(data)
    }
    return data
  }
})

export const uploadSingle = (fm) => {
  return uploadHttp.post('/upload_single', fm)
}

基础操作

单文件上传直接上传就行了 为了好看一般ui库都会隐藏掉input标签,然后搞一个button按钮,当用户点击这个按钮时,手动触发这个input的click时间,因为input的类型是file类型,默认动作就是唤起文件选择,选择文件后,会触发input的change事件,然后在change事件里拿到e.target.file,从而拿到了文件对象,拿到这个对象后存到状态里,然后点击上传按钮后,使用new FormData 创建一个formData对象,里面append 文件的key和value 并且调用文件上传接口,将这个文件对象传给后端,后端接收一下就完成了文件上传

 <section className="upload_box">
          <input
            ref={input1}
            type="file"
            onChange={handleChange1}
            className="upload_inp"
          />
          <div className="upload_button_box">
            <div
              className="upload_button select"
              onClick={() => input1.current.click()}>
              选择文件
            </div>
            <div className="upload_button upload" onClick={handleUploadSingle}>
              上传到服务器
            </div>
          </div>
          <div className="upload_tip">
            只能上传png/jpg/jeeg格式图片,且图片不能超过2MB
          </div>
          <ul className="upload_list">
            {Array.from(fileList1).map((item) => {
              return <li key={item.name}>{item.name}</li>
            })}
          </ul>
        </section>

状态和方法

  const input1 = useRef()
  const [fileList1, setFileList1] = useState([])
  const handleChange1 = (e) => {
    setFileList1(e.target.files)
  }
  const handleUploadSingle = async () => {
    let formData = new FormData()
    formData.append('file', fileList1[0])
    const res = await uploadSingle(formData)
  }

文件上传原理分析

(1)文件上传方式有很多,但底层的实现都是文件的读写操作(I/O读写)

文件上传的必要前提 1) 提供form表单、method必须是post 2) form表单的entype必须是multipart/form-data 3) 提供input type=“file”类的上传输入域

(2)文件上传到本地服务器的缺点:

  1. 当服务器重启,本地服务的文件没了

  2. 搭建服务器集群:A服务器1000, B服务器......... 客户第一次上传时访问的是A服务器。 客户第二次访问文件,访问的是B服务器

(3)如何解决本地服务器上传的缺点:

(1)自己搭建一个文件服务器;不会重启,维护

(2) 使用第三方的文件服务器