代码之家  ›  专栏  ›  技术社区  ›  Get Off My Lawn

读取多部分/窗体数据是不直接保存的

  •  0
  • Get Off My Lawn  · 技术社区  · 7 年前

    我正在尝试从http图像文件上传读取数据。它似乎读取了文件,但由于某种原因,输出文件的大小大约是原始文件的两倍。

    原稿:94.7KB

    当我在文本编辑器中打开这两个文件时,它们的行数相同,起始字符和结束字符相同。这让我相信上传的文件被保存为字符串而不是二进制数据。

    数据的读取:

    let body = ''
    req.on('data', data => {
      body += data.toString()
    }).on('end', data => {
      if (data) body += data.toString()
      // Rest of block
    })
    

    数据的保存:

    // If there is a filename grab the file data
    if (result.filename.length > 0) {
      // Create a temporary url
      let temp = join(os.tmpdir(), (Math.random() * 10000).toString(12).substr(5, 10))
    
      // Get the data between the blocks after the first two newlines
      let matches = item.match(/^.+?(\r\n\r\n|\n\n)(.+)/s)
    
      // Write the data to file
      fs.createWriteStream(temp).write(matches[2])
    }
    

    下面是数据的完整解析:

    http.createServer((req, res) => {
      let body = ''
      req.on('data', data => {
        body += data.toString()
      }).on('end', data => {
        if (data) body += data.toString()
        let boundary = req.headers['content-type'].split('boundary=')[1]
    
        // Split all the boundary items and loop over them
        body.split(new RegExp(`(--${boundary}|--${boundary}--)`)).forEach(item => {
          if (item.trim().toLowerCase().startsWith('content-disposition')) {
            item = item.trim()
            // Find the name and filename
            let result = item.split(':')[1].split(';').map(i => i.trim()).reduce((obj, itm) => {
              if (itm.startsWith('name=')) obj.name = itm.match(/^name="(.+)"/)[1]
              if (itm.startsWith('filename=')) obj.filename = itm.match(/^filename="(.+)"/)[1]
              return obj
            }, { name: '', filename: '' })
    
            // If there is a filename grab the file data
            if (result.filename.length > 0) {
              // Create a temporary url
              let temp = join(os.tmpdir(), (Math.random() * 10000).toString(12).substr(5, 10))
    
              // Get the data
              let matches = item.match(/^.+?(\r\n\r\n|\n\n)(.+)/s)
    
              // Write the data to file
              fs.createWriteStream(temp).write(matches[2])
            }
          }
        })
      })
    })
    
    1 回复  |  直到 7 年前
        1
  •  0
  •   Get Off My Lawn    7 年前

    所以,我在这两种情况下都是对的。。。

    首先,我必须将数据读取为二进制数据,如下所示:

    body += data.toString('binary')
    

    fs.createWriteStream(temp).write(matches[2], 'binary')
    

    这现在保存为正确的文件大小和图像是可读的!