Чтение multipart / form-data сохраняет неправильно - PullRequest
0 голосов
/ 26 августа 2018

Я пытаюсь прочитать данные с загрузки файла изображения http.Кажется, что файл читается, но по какой-то причине размер выходного файла примерно в два раза больше исходного файла.

Оригинал: 94,7 КБ
Временной файл: 168,8 КБ

Когда яОткройте оба файла в текстовом редакторе, они имеют одинаковое количество строк, а начальный и конечный символы одинаковы.Это оставляет меня верить, что загруженный файл сохраняется как строка вместо двоичных данных.

Я считаю, что важными частями являются следующие

Чтение данных:

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 Ответ

0 голосов
/ 27 августа 2018

Итак, я был несколько прав в обоих случаях ...

Во-первых, я должен прочитать данные как двоичные данные, например:

body += data.toString('binary')

Далее при сохранении мне нужносохранить в виде двоичных данных, например:

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

Теперь сохраняется правильный размер файла и изображение доступно для чтения!

...