文件上传总结:用原生解决前端文件上传操作(单个,多个,大文件切片)

news2025/1/11 19:48:00

目录

第一章 前言

第二章 理解文件上传的对象

2.1 如何利用原生实现

2.2 认识理解文件上传的四个对象

2.2.1 file对象

2.2.2 blob对象

2.2.3  formData对象

2.2.4 fileReader对象 

2.2.4.1 了解fileReader对象基本属性

2.2.4.2 了解 fileReader对象基本方法

2.2.4.3  了解fileReader对象基本事件

第三章 理解四个对象的使用

3.1 file与blob对象的使用

3.1.1 file对象转blob对象

3.1.2 blob对象转file对象

3.2 formData的使用

第四章 实战应用

4.1 单文件上传

4.2 多文件上传

4.3 切片上传

4.3.1 如何处理多个图片

4.3.2 实现切片上传 

第五章 源码


第一章 前言

相信我们很多人在项目中都会实现图片上传这么个功能,并且也会使用FormData和elementUI、antd等框架的upload组件实现,但是一延伸到原理、细节时就很难受,说不出所以然(小编也体验过,哈哈哈哈),所以如下是小编最近总结的点。

  • 用到的前端页面
    <input type="file" @change="fileChange" multiple />
    <button @click="submit">多选提交</button>
    <span v-for="(item, index) in fileList" :key="index">{{ item.name }}</span>
    <button @click="dealFile">处理图片信息</button>

第二章 理解文件上传的对象

2.1 如何利用原生实现

  • 利用input原生标签,type为file形式,multiple为多选,accept可以限制上传的文件类型,@change是使用的方法

<input type="file" @change="fileChange" multiple />

HTML input 标签 | 菜鸟教程

  • 我们可以看到最终返回的数据类型是File对象 

一个或多个文件对象组成的数组

 

2.2 认识理解文件上传的四个对象

2.2.1 file对象

  • 通过指定input标签type属性为file来读取files对象,是一个由一个或多个文件对象组成的数组

2.2.2 blob对象

  • 表示二进制类型的大对象。在数据库管理系统中,将二进制数据存储为一个单一个体的集合。Blob 通常是影像、声音或多媒体文件。在 JavaScript 中 Blob 类型的对象表示不可变的类似文件对象的原始数据, 使用构造函数创建。

2.2.3  formData对象

  • 利用它来提交表单、模拟表单提交,最大的优势就是可以上传二进制文件
  • 熟悉formData:

 前后端传参:掌握FormData并解决form-data类型传参问题_前端formdata传参-CSDN博客

2.2.4 fileReader对象 

  • 构造函数方式实例化一个fileReader对象,readAs()方法将文件对象读取成base64格式或者文本格式
2.2.4.1 了解fileReader对象基本属性
  • 直接使用时
const reader = new FileReader()
console.log('FileReader方法及属性:', reader)
  • 查看方法及属性:

 

  • FileReader.error(只读属性):读取文件时报的错误,null表示在读取用户所上传文件时没有出错
  • FileReader.readyState(只读属性):加载状态
状态值描述
0还没有加载任何数据
1数据正在被加载
2已完成全部的读取请求
  • FileReader.result(只读属性):表示文件的内容,仅在读取操作完成之后才有效,数据的格式取决于使用哪个方法(在2.2.4.2中)来启动读取操作
const reader = new FileReader()
console.log('FileReader方法及属性:', reader)
console.log('尝试使用只读属性error:', reader.error)
console.log('尝试使用只读属性readyState:', reader.readyState)
console.log('尝试使用只读属性result:', reader.result)

2.2.4.2 了解 fileReader对象基本方法
  •  我们顺着原型链往下找可以发现,该对象下还有以下四种方法

方法描述
FileReader.abort()终止读取操作
FileReader.readAsArrayBuffer()开始读取指定文件中的内容,一旦完成,result属性中保存的是被读取文件的ArrayBuffer数据对象
FileReader.readAsBinaryString()开始读取指定文件中的内容,一旦完成,result属性中保存的是所读取文件的原始二进制数据
FileReader.readAsDataURL()开始读取指定文件中的内容,一旦完成,result属性中是一个data:URL格式的Base64字符串以表示所读取文件的内容
FileReader.readAsText()开始读取指定文件中的内容,一旦完成,result属性中保存的是一个字符串以表示所读取的文件内容
  • 理解 FileReader.abort()的使用
dealFile () {
  this.fileList.forEach(item => {
    const reader = new FileReader()
    reader.abort()
    console.log('走到这了1')
    reader.onload = (res) => {
      console.log('走到这了2')
    }
  })
},

 

由于 FileReader.abort() 终止了读取操作,所以不会执行onload执行完毕触发的函数中的代码

  • 理解 FileReader.readAsArrayBuffer()的使用
dealFile () {
  this.fileList.forEach(item => {
    const reader = new FileReader()
    reader.readAsArrayBuffer(item)
    reader.onload = (res) => {
      console.log('执行readAsArrayBuffer返回的数据', res)
      console.log('返回的result值为:', res.target.result)
    }
  })
},

  • 理解 FileReader.readAsBinaryString() 的使用
dealFile () {
  this.fileList.forEach(item => {
    const reader = new FileReader()
    reader.readAsBinaryString(item)
    reader.onload = (res) => {
      console.log('执行readAsBinaryString返回的数据', res)
      console.log('返回的result值为:', res.target.result)
    }
  })
},

注意:该信息是原始的二进制文件信息 

  •  理解 FileReader.readAsDataURL() 的使用
dealFile () {
  this.fileList.forEach(item => {
    const reader = new FileReader()
    reader.readAsDataURL(item)
    reader.onload = (res) => {
      console.log('执行readAsDataURL返回的数据', res)
      console.log('返回的result值为:', res.target.result)
    }
  })
},

  • 理解 FileReader.readAsText() 的使用
dealFile () {
  this.fileList.forEach(item => {
    const reader = new FileReader()
    reader.readAsText(item)
    reader.onload = (res) => {
      console.log('执行readAsText返回的数据', res)
      console.log('返回的result值为:', res.target.result)
    }
  })
},

 注意:小编这里识别的是txt文档中的文字,如果上传的是图片,会说乱码

2.2.4.3  了解fileReader对象基本事件
  • 查看回调事件

事件方法描述
FileReader.onabort()处理abort事件,该事件在读取操作被中断时触发
FileReader.onerror()处理error事件,该事件在读取操作发生错误时触发
FileReader.onload()处理load事件,该事件在读取操作完成时触发
FileReader.onloadstart()处理loadstart事件,该事件在读取操作开始时触发
FileReader.onloadend()处理loadend事件,该事件在读取操作结束时(成功或失败)触发
FileReader.onprogress()处理progress事件,该事件正在读取时触发
  •  使用方法:
dealFile () {
  this.fileList.forEach(item => {
    const reader = new FileReader()
    reader.onabort = (res) => {
      console.log('读取中断了onabort', res)
    }
    reader.onerror = (res) => {
      console.log('读取发生错误了onerror', res)
    }
    reader.onload = (res) => {
      console.log('读取完成了onload', res)
    }
    reader.onloadstart = (res) => {
      console.log('读取开始了onloadstart', res)
    }
    reader.onloadend = (res) => {
      console.log('读取结束了onloadend', res)
    }
    reader.onprogress = (res) => {
      console.log('读取进行中onprogress', res)
    }
  })
},
  •  输出结果

  • 由上可知执行顺序为

 1、onloadstart -> onprogress -> onload  -> onloadend 

2、当使用 reader.abort() 方法中断读取时会执行onabort 

3、当读取错误时会执行onerror

第三章 理解四个对象的使用

3.1 file与blob对象的使用

3.1.1 file对象转blob对象

fileToBlob (file) {
   // new Blob([文件二进制流], 文件类型)
   const blob = new Blob([file], { type: file.type }) // 直接利用Blob的方法
   console.log('blob', blob)
   return blob
},

3.1.2 blob对象转file对象

// blob二进制流转file二进制流注意要再携带参数文件名
blobToFile (blob, fileName) {
  // new File([blob二进制流], 文件名, 文件类型)
  const file = new File([blob], fileName, { type: blob.type })
  console.log('file', file)
},

3.2 formData的使用

前后端传参:掌握FormData并解决form-data类型传参问题_前端formdata传参-CSDN博客

第四章 实战应用

4.1 单文件上传

  • 利用input元素的accept属性限制上传文件的类型,multiple限制能否多选
  •  完整代码:

        -- html部分——

<template>
  <div>
    <input type="file" @change="fileChange"/>
    // 该按钮支持单个文件上传与多个文件上传
    <button @click="submit">多选提交</button>
    <span v-for="(item, index) in fileList" :key="index">{{ item.name }}</span>
  </div>
</template>

         -- js部分——

<script>
import axios from 'axios'
export default {
  data () {
    return {
      fileList: [] // 定义空数组存储多个文件
    }
  },
  components: {
  },
  methods: {
    fileChange (e) {
      // 一个由不同文件对象组成的对象
      console.log('文件对象e,文件方法:e.target.files', e, e.target.files)
      // 单文件上传
      this.fileList = []
      this.fileList.push(e.target.files[0])
    },
    async submit () {
      const _formdata = new FormData()
      // 循环fileList,每次都创建一个formdata对象上传
      this.fileList.forEach(async item => {
        // 转二进制流形式上传
        const blob = new Blob([item], { type: item.type })
        console.log('blob', blob)
        _formdata.append('files', blob, item.name)
      })
      axios({
        url: '/api/upload',
        method: 'POST',
        headers: {
          'Content-type': 'multipart/form-data'
        },
        data: _formdata
      }).then(response => {
        console.log(response)
      }).catch(err => {
        console.log(err)
      })
    }
  }
}

        -- 页面展示:

  • 上传成功(只选择一个文件上传即可)

  •  传参

4.2 多文件上传

  • 将多个文件放到一个数组内,然后循环这个数组内的文件对象,利用formdata实现;可以每处理一次,然后调用一次接口,上传一个文件;也可以将数组中的文件对象都处理好之后,调用接口上传所有文件

  • 注意:该接口的实现需要与后端商量好可以如何上传

  • html部分——
<template>
  <div>
    // 支持批量上传
    <input type="file" @change="fileChange" multiple />
    // 该按钮支持单个文件上传与多个文件上传
    <button @click="submit">多选提交</button>
    <span v-for="(item, index) in fileList" :key="index">{{ item.name }}</span>
  </div>
</template>
  • 方法一:遍历数组中的文件对象,利用formdata处理值,每处理一次,调用一次方法
<script>
import axios from 'axios'
export default {
  data () {
    return {
      fileList: [] // 定义空数组存储多个文件
    }
  },
  components: {
  },
  methods: {
    fileChange (e) {
      // 一个由不同文件对象组成的对象
      console.log('文件对象e,文件方法:e.target.files', e, e.target.files)
      // 检测e.target.files是否有多个文件
      if (e.target.files.length > 1) {
        // 如果上传了多个文件将其合并
        this.fileList = [...this.fileList, ...e.target.files]
        // this.fileList = this.fileList.concat(e.target.files)
      } else {
        this.fileList.push(e.target.files[0])
      }
    },
    async submit () {
      // 循环fileList,每次都创建一个formdata对象上传
      this.fileList.forEach(async item => {
        const _formdata = new FormData()
        const blob = new Blob([item], { type: item.type })
        console.log('blob', blob)
        _formdata.append('files', blob, item.name)
        axios({
          url: '/api/upload',
          method: 'POST',
          headers: {
            'Content-type': 'multipart/form-data'
          },
          data: _formdata
        }).then(response => {
          console.log(response)
        }).catch(err => {
          console.log(err)
        })
      })
    }
  }
}

 

  •  方法二:遍历数组中的文件对象,利用formdata处理值,利用formdata.append将每一次处理的值添加到formdata对象中,最后上传所有文件
<script>
import axios from 'axios'
export default {
  data () {
    return {
      fileList: [] // 定义空数组存储多个文件
    }
  },
  components: {
  },
  methods: {
    fileChange (e) {
      // 一个由不同文件对象组成的对象
      console.log('文件对象e,文件方法:e.target.files', e, e.target.files)
      // 检测e.target.files是否有多个文件
      if (e.target.files.length > 1) {
        // 如果上传了多个文件将其合并
        this.fileList = [...this.fileList, ...e.target.files]
        // this.fileList = this.fileList.concat(e.target.files)
      } else {
        this.fileList.push(e.target.files[0])
      }
    },
    async submit () {
      const _formdata = new FormData()
      // 循环fileList,每次都创建一个formdata对象上传
      this.fileList.forEach(async item => {
        // 转二进制流形式上传
        const blob = new Blob([item], { type: item.type })
        console.log('blob', blob)
        _formdata.append('files', blob, item.name)
      })
      axios({
        url: '/api/upload',
        method: 'POST',
        headers: {
          'Content-type': 'multipart/form-data'
        },
        data: _formdata
      }).then(response => {
        console.log(response)
      }).catch(err => {
        console.log(err)
      })
    }
  }
}

 

  • 多文件上传两种方法可能会涉及到的问题:
  1. 当上传数量过多时(上百上千时),处理一条数据发一个请求,造成频繁的调用接口,对服务器会有一定的影响;用户频繁上传大量的图片,服务器需要处理和存储这些图片,会消耗大量的带宽和存储空间,这可能导致服务器负载增加,影响了服务器的性能表现。此外,图片上传过程中的网络传输也会占用服务器的网络资源,对其他用户的访问速度可能会有所影响。
  2. 但时当一次性上传或者打包上传特别大的文件时,又有可能出现上传文件过大,后端处理文件的时间太长,但是前端设置的响应时间没有这么长,到了时间之后前端就会报错,那么这上传又如何处理

4.3就是如何解决上述两个问题中的方法之一:分片上传

4.3 切片上传

4.3.1 如何处理多个图片

  • 当用户上传大量图片时,如果我们使用4.2中了两种方法会出现的问题已经了解了,那么我们如何解决呢,如何处理这批量的图片呢?
  • 小编给出如下方法:

input标签设置multiple上传大量文件 -> 上传时将每一个文件的二进制流封装成一个promise对象 ->每一个promise对象push到一个数组 -> 利用promise.all确定数组中promise的状态值都是成功状态,promise.all为成功态才会执行代码 -> 遍历promise数组获取里面的二进制流文件 -> 利用jszip组件将所有的文件打包成压缩包的二进制流 -> (前端可以利用file-saver下载查看压缩包内容) -> 最后将改压缩包的二进制流进行分片上传

  • 处理多个图片的代码:

html部分——

<template>
  <div>
    <input type="file" @change="fileChange" multiple/>
    <button @click="imageCompress">压缩图片</button>
    <span v-for="(item, index) in fileList" :key="index">{{ item.name }}</span>
  </div>
</template>

js部分——

<script>
import axios from 'axios'
import JSZip from 'jszip'
// import FileSaver from 'file-saver'

export default {
  data () {
    return {
      fileList: [], // 定义空数组存储多个文件
      filesPromises: [] // 存放二进制文件流的promise数组
    }
  },
  components: {
  },
  methods: {
    // 利用promise处理多个图片
    // 将每一个文件的二进制流封装成一个promise对象
    dealFiles (file) {
      return new Promise((resolve, reject) => {
        resolve({ file })
      })
    },
    // 图片压缩
    imageCompress () {
      // 利用promise.all
      Promise.all(this.filesPromises).then(async (files) => {
        // 定义一个JSZip实例
        const zip = new JSZip()
        // 遍历数据 遍历promise数组获取里面的二进制流文件
        files.forEach(async (item, index) => {
          const { file } = item
          console.log('每一个二进制流文件数据为:', file)
          // 添加需要压缩的文件,二进制流的形式
          await zip.file(file.name, file)
        })
        // 下载压缩包
        zip.generateAsync({ type: 'blob' }).then((content) => {
            console.log('压缩包的二进制流信息', content)
            // 下载上面压缩的压缩包
            FileSaver.saveAs(content, '合并的内容' + '.zip')
        })
      }).catch(err => {
        console.log(err)
      })
    },
    fileChange (e) {
      // 一个由不同文件对象组成的对象
      console.log('文件对象e,文件方法:e.target.files', e, e.target.files)
      // 检测e.target.files是否有多个文件
      if (e.target.files.length > 1) {
        this.fileList = [...this.fileList, ...e.target.files]
        // this.fileList = this.fileList.concat(e.target.files)
      } else {
        this.fileList.push(e.target.files[0])
      }
      // 处理文件信息成promise对象
      // 每一个promise对象push到一个数组
      this.fileList.forEach(item => {
        this.filesPromises.push(this.dealFiles(item))
      })
      console.log('存放文件的列表', this.fileList, this.filesPromises)
    }
  }
}
</script>

 页面效果——

上传多个文件:

将每一个promise对象push到一个数组中 :

查看处理后的数据信息:

利用file-saver插件中的方法下载的内容: 

 

成功利用jszip插件中的方法将上传的图片打压成压缩包: 

 

4.3.2 实现切片上传 

  •  切片上传的核心就是利用二进制流中的size(文件大小)的slice方法切割数据流,将每一段二进制流数据发送请求给后端,当发送完成后,由后端合并,最终返回前端想要的数据

 html部分——

<template>
  <div>
    <input type="file" @change="fileChange" multiple/>
    <button @click="shardingSubmit">分片提交</button>
    <button @click="imageCompress">压缩图片</button>
    <span v-for="(item, index) in fileList" :key="index">{{ item.name }}</span>
    <div>
      上传进度:{{ precent }}%
    </div>
  </div>
</template>

js部分—— (先点击压缩图片按钮,再点击分片提交)

注意:一定要与后端沟通好传参的格式

<script>
import axios from 'axios'
import JSZip from 'jszip'
// import FileSaver from 'file-saver'

export default {
  data () {
    return {
      fileList: [], // 定义空数组存储多个文件
      filesPromises: [], // 存放二进制文件流的promise数组
      compreeContent: null
    }
  },
  components: {
  },
  methods: {
    // 分片上传
    async shardingSubmit () {
      const size = 1024 * 1024
      // 注意 ======== 从这开始时小编传一个文件做的切片上传测试
      // const fileData = this.fileList[0]
      // console.log('fileData', fileData)
      // // const fileName = fileData.name.split('.')[0]
      // const blob = new Blob([fileData], { type: fileData.type })
      // 注意 ======== 到这结束,获取blob二进制数据流的过程
      const blob = this.compreeContent
      const blobSize = blob.size
      let current, i
      console.log('blob', blob, blob.size)
      for (current = 0, i = 0; current < blobSize; current += size, i++) {
        const _formdata = new FormData()
        // 一次添加1M大小的切片  注意添加时的说明一般为文件名,后端接收后按照文件名标识拼接
        // 传参格式(与后端沟通好)
        _formdata.append('file', blob.slice(current, current + size))
        _formdata.append('chunkIndex', i + 1)
        _formdata.append('chunkTotal', Math.ceil(blobSize / size))
        _formdata.append('name', `片段${Math.ceil(blobSize / size)}`)
        // 这里可以通过传参动态解决
        _formdata.append('suffix', 'zip')
        // _formdata.append('suffix', 'png')
        axios({
          url: '/api/part',
          method: 'POST',
          headers: {
            'Content-type': 'multipart/form-data'
          },
          data: _formdata
        }).then(response => {
          console.log(response)
          // 计算当前上传进度,展示到页面
          // 小编只是实现了分片上传的逻辑,进度条未处理好
          this.precent = Math.ceil(((current) / blobSize) * 100)
        }).catch(err => {
          console.log(err)
        })
      }
    },
    // 利用promise处理多个图片
    // 将每一个文件的二进制流封装成一个promise对象
    dealFiles (file) {
      return new Promise((resolve, reject) => {
        resolve({ file })
      })
    },
    // 图片压缩/文件
    imageCompress () {
      // 利用promise.all
      Promise.all(this.filesPromises).then(async (files) => {
        // 定义一个JSZip实例
        const zip = new JSZip()
        // 遍历数据 遍历promise数组获取里面的二进制流文件
        files.forEach(async (item, index) => {
          const { file } = item
          console.log('每一个二进制流文件数据为:', file)
          // 添加需要压缩的文件,二进制流的形式
          await zip.file(file.name, file)
        })
        // 下载压缩包
        zip.generateAsync({ type: 'blob' }).then((content) => {
            console.log('压缩包的二进制流信息', content)
            this.compreeContent = content
            // 下载上面压缩的压缩包
            // FileSaver.saveAs(content, '合并的内容' + '.zip')
        })
      }).catch(err => {
        console.log(err)
      })
    },
    fileChange (e) {
      // 一个由不同文件对象组成的对象
      console.log('文件对象e,文件方法:e.target.files', e, e.target.files)
      // 检测e.target.files是否有多个文件
      if (e.target.files.length > 1) {
        this.fileList = [...this.fileList, ...e.target.files]
        // this.fileList = this.fileList.concat(e.target.files)
      } else {
        this.fileList.push(e.target.files[0])
      }
      // 处理文件信息成promise对象
      // 每一个promise对象push到一个数组
      this.fileList.forEach(item => {
        this.filesPromises.push(this.dealFiles(item))
      })
      console.log('存放文件的列表', this.fileList, this.filesPromises)
    }
  }
}
</script>

 后端合并结果:(这里只是demo,具体情况具体解析)

第五章 源码

batch_file_upload: 文件上传(单个、多个、分片)代码

参数说明:

  • 单个/多个上传

  • 分片上传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1444392.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[office] Excel2019函数MAXIFS怎么使用?Excel2019函数MAXIFS使用教程 #知识分享#微信#经验分享

Excel2019函数MAXIFS怎么使用&#xff1f;Excel2019函数MAXIFS使用教程 Excel2019函数MAXIFS怎么使用&#xff1f;这篇文章主要介绍了Excel2019函数MAXIFS使用教程,需要的朋友可以参考下 在今年&#xff0c;Excel除了新版本Excel2019&#xff0c;其中有一个新功能MAXIFS函数&am…

知识价值2-什么是IDE?新手用哪个IDE比较好?

IDE是集成开发环境&#xff08;Integrated Development Environment&#xff09;的缩写&#xff0c;是一种软件应用程序&#xff0c;旨在提供集成的工具集&#xff0c;以方便开发人员进行软件开发。IDE通常包括代码编辑器、编译器、调试器和其他工具&#xff0c;以支持软件开发…

使用耳机壳UV树脂制作一个耳机壳需要多长时间?

使用耳机壳UV树脂制作一个耳机壳所需的时间取决于多个因素&#xff0c;包括工艺流程、加工方式、设备和技术水平等。一般来说&#xff0c;制作一个耳机壳需要数小时到数天不等。 以下是影响制作时间的几个主要因素&#xff1a; 获取耳模时间&#xff1a;获取耳模的时间取决于…

最适合新手的SpringBoot+SSM项目《苍穹外卖》实战—(一)项目概述

黑马程序员最新Java项目实战《苍穹外卖》&#xff0c;最适合新手的SpringBootSSM的企业级Java项目实战。 项目简介 《苍穹外卖》项目的定位是一款为餐饮企业&#xff08;餐厅、饭店&#xff09;定制的软件产品。该项目是一个在线外卖订购系统&#xff0c;顾客可以通过网站或者…

RabbitMQ的延迟队列实现[死信队列](笔记一)

关于死信队列的使用场景不再强调&#xff0c;只针对服务端配置 注意&#xff1a; 本文只针对实现死信队列的rabbitMQ基本配置步骤进行阐述和实现 目录 1、docker-compose 安装rabbitMq2、查看对应的版本及插件下载3、安装插件和检测 1、docker-compose 安装rabbitMq a、使用d…

错误的集合(力扣刷题)

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 由于作者比较菜&#xff0c;还没学malloc这个函数&#xff0c;因此这个题目只写一些与原题大致的思路。 题目链接&#xff1a;645. 错误的集合 - 力扣…

任务管理软件的实用价值及优选推荐:提升工作效率的利器

任务管理软件是一种用于组织任务、将任务分配给个人并监控其进展的软件。该软件可以帮助确保任务在预算内按时完成。它在协同工作环境中特别有用&#xff0c;在这种环境中多人在处理需要跟踪和监视的任务。无论是初创公司、中小型企业还是大型组织&#xff0c;都可以从任务管理…

【书生·浦语大模型实战营】学习笔记1

大模型成为发展通用人工智能的重要途经 专用模型&#xff1a;针对特定任务&#xff0c;一个模型解决一个问题 通用大模型&#xff1a;一个模型应对多种任务、多种模态 书生浦语大模型系列 上海人工智能实验室 轻量级、中量级、重量级 7B 和 123B的轻量级和中量级大模型都是开源…

统计数字出现次数的数位动态规划解法-数位统计DP

在处理数字问题时,我们经常遇到需要统计一定范围内各个数字出现次数的情况。这类问题虽然看起来简单,但当数字范围较大时,直接遍历统计的方法就变得不再高效。本文将介绍一种利用数位动态规划(DP)的方法来解决这一问题,具体来说,是统计两个整数a和b之间(包含a和b)所有…

【开源】JAVA+Vue.js实现车险自助理赔系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 车辆档案模块2.4 车辆理赔模块2.5 理赔照片模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 车辆表3.2.3 理赔表3.2.4 理赔照片表 四、系统展示五、核心代码5.1 查询车…

杨辉三角的变形(数学)

题目 import java.util.Scanner;public class Main {public static void main(String[] args) { // 1 // 1 1 1 // 1 2 3 2 1 // 1 3 6 7 6 3 1 // 1 4 10 16 19 16 10 4 1Scanner sc new Scanner(System.in);int n sc.nextInt();int[][] res new int[n1][2*n];for(i…

《统计学简易速速上手小册》第3章:概率分布与抽样技术(2024 最新版)

文章目录 3.1 重要的概率分布3.1.1 基础知识3.1.2 主要案例&#xff1a;顾客到访分析3.1.3 拓展案例 1&#xff1a;产品缺陷率分析3.1.4 拓展案例 2&#xff1a;日销售额预测 3.2 抽样方法与推断3.2.1 基础知识3.2.2 主要案例&#xff1a;顾客满意度调查3.2.2 拓展案例 1&#…

Java项目:19 基于SpringBoot的医院管理系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 医院管理系统 分为三个角色 管理员、医生、病人 管理员的主要功能&#xff1a;系统管理、医生管理、患者管理、预约管理、病史管理、住院信息管理、管…

C++ | string类按位赋值小技巧

一切的起因是string类的谜之初始化。 在写代码的时候&#xff0c;我发现即使没有用字符串初始化string对象&#xff0c;也可以对string对象进行下标操作&#xff0c;就像这样&#xff1a; #include<iostream> #include<string> using namespace std; int main() {…

【Go】一、Go语言基本语法与常用方法容器

GO基础 Go语言是由Google于2006年开源的静态语言 1972&#xff1a;&#xff08;C语言&#xff09; — 1983&#xff08;C&#xff09;—1991&#xff08;python&#xff09;—1995&#xff08;java、PHP、js&#xff09;—2005&#xff08;amd双核技术 web端新技术飞速发展&…

探索Spring Validation:优雅实现后端数据验证的艺术

在现代Web应用开发中&#xff0c;数据验证是一项至关重要的任务&#xff0c;确保应用程序接收到的用户输入符合预期规范&#xff0c;不仅能够提高系统的健壮性&#xff0c;也能有效防止潜在的安全漏洞。Spring Framework通过其内置的Spring Validation模块&#xff0c;为我们提…

案例:CentOS8 在 MySQL8.0 实现半同步复制

异步复制 MySQL 默认的复制即是异步的&#xff0c;主库在执行完客户端提交的事务后会立即将结果返给给客户端&#xff0c;并不关心从库是否已经接收并处理&#xff0c;这样就会有一个问题&#xff0c;主节点如果 crash 掉了&#xff0c;此时主节点上已经提交的事务可能并没有传…

进程间通信-消息队列

消息队列的公共资源是链表结构。 通信双方不会和消息队列进行挂接&#xff0c;而是像管道一样&#xff0c;访问内存中的消息队列。 消息队列由操作系统维护&#xff0c;但是由通信的某一方创建和删除 通信双方都需要获取到消息队列&#xff0c;和共享内存一样。 当发送方有数据…

ARP欺骗攻击利用之抓取https协议的用户名与密码

1.首先安装sslstrip 命令执行&#xff1a;apt-get install sslstrip 2.启动arp欺骗 arpspoof -i ech0 -t 192.168.159.148 192.168.159.2 arpspoof -i ech0(网卡) -t 目标机ip 本地局域网关 3.命令行输入: vim /etc/ettercap/etter.conf进入配置文件 找到下红框的内容&a…