input上传图片预览

前端代码示例

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>图片上传</title>
</head>

<body>
  <form action="http://localhost:3000/api/upload" method="post" enctype="multipart/form-data">
    <div onclick='chooseImg()'>上传</div>

    <p style="display:none;"><input id="uploadInput" type="file" name="file" onchange="updateUploadImg(this);" accept="image/gif, image/jpeg,image/jpg,image/png" multiple>
    </p>

    <input type="text" name="text" value="123124">
    <p><input type="submit" value="Send file"></p>
  </form>
  <div onclick="submit()">
    js提交
  </div>
</body>
<script type="text/javascript">
  function chooseImg() {
    document.getElementById('uploadInput').click()
  }

  function updateUploadImg(el) {
    var files = el.files
    for (let i = 0; i < files.length; i++) {
      const file = files[i]
      if (!file.type.startsWith('image/')) {
        continue
      }
      const img = document.createElement("img")
      img.file = file;
      img.src = getObjectURL(file)
      document.body.appendChild(img)
    }
  }

  function getObjectURL(file) {
    var url = null
    if (window.createObjectURL != undefined) { //basic
      url = window.createObjectURL(file)
    } else if (window.URL != undefined) { //mozilla(firefox)兼容火狐
      url = window.URL.createObjectURL(file)
    } else if (window.webkitURL != undefined) { //webkit or chrome
      url = window.webkitURL.createObjectURL(file)
    }
    return url
  }

  function submit() {
    var xhr = XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject
    var fd = new FormData()
    var fileList = document.getElementById('uploadInput').files
    if (!fileList.length) {
      return
    }
    for (var i = 0; i < fileList.length; i++) {
      fd.append('file', fileList[i])
    }
    fd.append('text', 12312312)
    xhr.open('POST', 'http://localhost:3000/api/upload', true)
    xhr.send(fd)
    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        var obj = JSON.parse(xhr.responseText); //返回值
        console.log(obj);
      }
    }
  }
</script>

</html>

下面是后端nodejs代码示例
前端上传文件,后端接收并将图片地址返回给前端

const Koa = require('koa')
const app = new Koa()
const serve = require('koa-static')
const koaBody = require('koa-body')
const {resolve}=require('path')
const cors = require('@koa/cors')
const {
  initRouter
} = require('./routes')

app.use(koaBody({
  multipart:true,
  formidable: {
        uploadDir: resolve(__dirname, 'public/uploads')
    }
}))
app.use(cors())
async function start() {
  initRouter(app)
  app.use(serve(__dirname + '/public'))
}
start()
app.listen(3000, () => {
  console.log('sever listen 3000')
})

下面是处理文件上传的路由文件
前端单个字段可以上传多张图片,多张图片是返回对象是一个数组,单张是返回是一个对象

const Router = require('koa-router')
const fs = require('fs')
const path = require('path')
const router = new Router({
  prefix: '/api'
})
router.post('/upload', async (ctx, next) => {
  let fileObj = {}
  let files = ctx.request.files
  for (let i in ctx.request.files) {
    let file = ctx.request.files[i]
    let isSingle = false
    if (!Array.isArray(file)) {
      file = [file]
      isSingle = true
    }
    for (let j = 0; j < file.length; j++) {
      let singleRes = resolveSingleFile(file[j])
      if (singleRes) {
        // 单个文件直接赋值
        if (isSingle) {
          fileObj[i] = singleRes
          break
        } else if (!isSingle && !fileObj[i]) { // 如果是多个文件并且fileObj[i]还没有被赋值
          fileObj[i] = []
        }
        fileObj[i].push(singleRes)
      }
    }
  }
  ctx.body = {
    status: 1,
    data: fileObj
  }
})

function deleteUploadFile(filepath) {
  fs.unlink(filepath, function(err) {
    if (err) {
      console.log(err)
    }
  })
}

function resolveSingleFile(file) {
  let fname = file.name
  let fpath = file.path
  let res = {}
  if (file.size && file.path) {
    let extArr = fname.split('.')
    let ext = extArr[extArr.length - 1]
    let newPath = fpath + '.' + ext
    fs.renameSync(fpath, newPath)
    res.name = fname
    res.url = `http://localhost:3000/uploads/${ path.basename(newPath)}`
  } else {
    // 路径没找到直接返回
    if (!file.path) {
      return
    }
    // 文件大小为0直接删除
    deleteUploadFile(file.path)
  }
  return res
}
module.exports = {
  initRouter: function(app) {
    app
      .use(router.routes())
      .use(router.allowedMethods())
  }
}

返回格式示例

 {
  "status": 1,
  "data": {
    "file": { "name":"...","url":"..."},
    "file1":[ { "name":"...","url":"..."}]
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355