обновить бинарные файлы в nodejs - PullRequest
1 голос
/ 16 февраля 2020

Я пытаюсь работать с двоичными файлами, используя Nodejs.

Я пытаюсь получить двоичный файл от клиента, открыть двоичный файл, преобразовать в шестнадцатеричный формат, заменить данные и вернуть новый двоичный файл клиенту.

app.use('/read-binary-file',(req,res)=>{
    try {
        let content = fs.readFileSync(file_path);
        console.log('content',content)
        res.status(200).send({content})
      } catch(err) {
        console.error(err);
      }
})

Я написал код, который принимает существующий файл, попробуйте прочитать его, при печати я получаю буфер

content <Buffer 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... >  

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

enter image description here

У меня есть несколько вопросов:

  1. как преобразовать двоичный код в гекс?
  2. как заменить данные в шестнадцатеричном файле и затем вернуть их клиенту?
  3. как отобразить их в коде как 16-битные?
  4. Какой лучший способ сохранить их в базе данных? сохранить файл и затем в базе данных сохранить только путь?

Любые документы, которые могут помочь.

Ответы [ 2 ]

5 голосов
/ 16 февраля 2020

1) Преобразовать из двоичного в шестнадцатеричное:

const file = fs.readFileSync("./test");
const str = file.toString("hex");

2) Заменить данные и вернуть клиенту:

let newStr = str.replace( "00", "FF" );
let buffer = Buffer.from( newStr, "hex" );

3) Отображение в 16 битах:

for ( let i = 0; i < newStr.length; i+=16 ){ 
  console.log( newStr.slice( i, i+16 ) + "\n" );  
}

4) Сохраните файл в доступной для записи папке загрузки и сохраните URL-путь к загруженному в базе данных. Это мое предложение, исходя из моего опыта. Подробнее о том, хотите ли вы выбрать сохранение изображений в базе данных (в формате Blob), можно прочитать в этом сообщении Quora: Это плохой дизайн для хранения изображений в виде BLOB-объектов в базе данных?


Вот базовая c установка, которая может вам помочь:

/ test

ABC

/ app. js

const express = require('express');
const app = express();
const fs = require('fs');

app.use("/test", (req, res) => {

    const file = fs.readFileSync("./test");     // READ FILE AS BINARY
    const str = file.toString("hex");           // CONVERT TO HEX
    let newStr = str.replace(/41|43/g, "42");   // REPLACE HEX CHARACTERS
    let buffer = Buffer.from(newStr, "hex");    // CREATE BUFFER FROM HEX

    // SEND TO USER AS DOWNLOAD
    res.setHeader('Content-disposition', 'attachment; filename=test-edited.txt');
    res.setHeader('Content-type', 'text/plain');
    res.charset = 'UTF-8';
    res.write( buffer );
    res.end();

});

app.listen(3000, () => console.log('Server Running...'));

Тестовый файл содержит символы AB C, они преобразуются в BBB и затем загружаются.

Вы можете выбрать вывод файла другого типа, задав соответствующее имя файла и MIME type (Content-Type), например, для загрузки изображения в формате PNG:

    res.setHeader('Content-disposition', 'attachment; filename=output.png');
    res.setHeader('Content-type', 'image/png');

Примечание: для прямой двоичной манипуляции, без промежуточного шестнадцатеричного преобразования, см. Ответ Christos Lytras ,

3 голосов
/ 18 февраля 2020

Вам не нужно преобразовывать двоичные данные в шестнадцатеричные, чтобы что-то заменить в них. Если вы хотите заменить данные внутри двоичного файла, то это означает, что вы знаете точно , что вы хотите заменить, что означает заданные c смещения, основанные на некоторых шаблонах, структуре данных или байтных фрагментах, которые вы будете использовать. надо искать. Если вы хотите создать онлайн-редактор hex для своих клиентов, то это совсем другое дело, и оно включает в себя не только логику бэкэнда c, но и пользовательский интерфейс, который позволит пользователям загружать / редактировать и скачивать файлы.

Замена двоичных данных двоичными данными с фиксированным смещением с помощью Buffer.copy:

// First 3 bytes of data Buffer will be replaced with 0x02 0x03 0x04 bytes
Buffer.alloc(3, new Uint8Array([0x02, 0x03, 0x04])).copy(data, 0, 0, 3);

Использование Buffer.indexOf для поиска шаблонов двоичных данных:

// Loading a PNG image
const data = fs.readFileSync('js-logo-16x16.png');

// Search for the PNG signature using Buffer.indexOf
const sigpos = data.indexOf(Buffer.from('PNG'));

if (sigpos >= 0) {
  // If signature pos found (!= -1), replace it with JPG using Buffer.write
  data.write('JPG', sigpos, 3);
}

Вы можете использовать простые l oop и логику манипулирования строками c для печати шестнадцатеричных данных:

// For Nodejs using a Buffer
function displayHexData(data) {
  for (let addr = 0; addr <= data.length; addr += 16) {
    const displayAddr = addr.toString(16).toUpperCase().padStart(8, '0');
    const block = data.slice(addr, Math.min(addr + 16, data.length));

    let hexblock = block.toString('hex');

    if (addr + 16 > data.length) {
      hexblock += '  '.repeat(16 - (data.length - addr));
    }

    const charsblock = Array.from(block)
      .map(b => b >= 32 && b <= 126 ? String.fromCharCode(b) : '.')
      .join('');

    console.log(displayAddr, hexblock.split(/(.{2})/).join(' '), charsblock);
  }
}

выведет что-то вроде этого:

Nodejs binary data hex display

и для веб Javascript:

// 16 x 16 PNG 8-bit
const base64Data = 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQBAMAAADt3eJSAAAAA3NCSVQICAjb4U/gAAAAMFBMVEUAAADQvhqQghFBOgj/7iAjIAT84x+6qxdqYA3u1x2nlxT//CIxLAZKQwnOuhnZyBvQr3QtAAAACXBIWXMAAAsSAAALEgHS3X78AAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAAFNJREFUCJljSIMCBlIZKW4ubmBGhkrtdTDD1Yz5rBuI4XOTyQUs4mPdEA4SSfGx3n7gCZDxKfV+24fVQEYBQyED6zQgI39d2qyVIMUpW9Kyt6UBAGorNUfBuVldAAAAAElFTkSuQmCC';

const data = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));

displayHexData(data);

function displayHexData(data) {
  let result = '';
  
  for (let addr = 0; addr <= data.length; addr += 16) {
    const displayAddr = addr.toString(16).toUpperCase().padStart(8, '0');
    const block = data.slice(addr, Math.min(addr + 16, data.length));

    let hexblock = Array.from (block)
      .map (b => b.toString(16).toUpperCase().padStart(2, "0"))
      .join('');

    if (addr + 16 > data.length) {
      hexblock += '  '.repeat(16 - (data.length - addr));
    }
    
    const charsblock = Array.from(block)
      .map(b => b >= 32 && b <= 126 ? String.fromCharCode(b) : '.')
      .join('');

    result += `${displayAddr} ${hexblock.split(/(.{2})/).join(' ')} ${charsblock}\n`;
  }
  
  document.getElementById('hex').appendChild(document.createTextNode(result));
}
#hex {
  font-size: small;
}

Что касается сохранения двоичных данных в базе данных, то, конечно, это зависит от типа базы данных. Большинство баз данных поддерживают тип данных Binary Large Object BLOB, например MySQL, и вы используете его для хранения двоичных данных. Сохранение файла в файловой системе и просто использование поля для сохранения его пути также является довольно хорошим способом для go, но вам придется обрабатывать резервные копии / восстановления, включая те каталоги, в которых будут храниться файлы.

...