MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

convertendo de blob para binário para salvá-lo no mongodb


Então, acho que seu problema está nesta linha:
new_project.picture.data = fs.readFileSync(req.body.picture[0]);

E é a coluna da tabela mongoDB que você está inserindo data em que está lhe dando esse erro. Ele está esperando uma string ou Buffer e você deu a ele um objeto File.

Você pode obter uma string de byte base64 usando o que postei aqui , que tentarei integrar ao seu código, abaixo:

Você precisa garantir que tenha uma variável para coletar seu(s) arquivo(s). É assim que eu tenho o topo da minha página configurado:
import React from 'react'
import Reflux from 'reflux'
import {Form, Card, CardBlock, CardHeader, CardText, Col, Row, Button } from 'reactstrap'
import actions from '~/actions/actions'
import DropZone from 'react-dropzone'

// stores
import SomeStore from '~/stores/someStore.jsx'

Reflux.defineReact(React)
export default class myUploaderClass extends Reflux.Component {
  constructor(props) {
    super(props);
    this.state = {
        attachments: [],
    };
    this.stores = [
        SomeStore,
    ]
    ....

Em seguida, vincule novas funções:
    ....
    this.getData = this.getData.bind(this);
    this.processFile = this.processFile.bind(this);
    this.errorHandler = this.errorHandler.bind(this);
    this.progressHandler = this.progressHandler.bind(this);
  } // close constructor

Em seguida, trabalhamos para fornecer os bytes aos attachments e enviando para new_project.picture.data . Para mim, eu uso uma função que executa onDrop da DropZone usando onDrop={this.uploadFile} . Eu realmente não posso dizer o que você está fazendo porque não tenho ideia do que filesToUpload refere-se a. Meu uploadFile se parece com isso:
uploadFile(event){
  this.setState({
    files: event,
  });

  document.getElementById('docDZ').classList.remove('dragover');
  document.getElementById('progress').textContent = '000';
  document.getElementById('progressBar').style.width = '0%';

  this.state.files = event;  // just for good measure
  for (let i = 0; i < this.state.files.length; i++) {
    const a = i + 1;
    console.log('in loop, pass: ' + a);
    const f = this.state.files[i];

    this.getData(f); // this will load the file to SomeStore.state.attachments
  }
}

e este seria o getData função executada para cada arquivo descartado/adicionado ao DropZone:
getData(f) {
    const reader = new FileReader();
    reader.onerror = this.errorHandler;
    reader.onprogress = this.progressHandler;
    reader.onload = this.processFile(f);
    reader.readAsDataURL(f);
}

Então processFile() do onload corre:
processFile(theFile) {
  return function(e) {
    const bytes = e.target.result.split('base64,')[1];
    const fileArray = [];

    // *** Collect any existing attachments ***
    // I found I could not get it from this.state, but had to use
    // my store, instead
    if (SomeStore.state.attachments.length > 0) {
      for (let i=0; i < SomeStore.state.attachments.length; i++) {
        fileArray.push(SomeStore.state.attachments[i]);
     }
    }

    // Add the new one to this.state
    fileArray.push(bytes);

    // Update the state
    SomeStore.setState({
      attachments: fileArray,
    });
    // This seemed to automatically add it to this.state, for me.
  }
}

Depois de ter isso, você deve ser capaz de fazer:
new_project.picture.data = this.state.attachments[0];

Caso contrário, por algum motivo, você pode tentar chamar isso dentro de exports.create_a_project() , como a primeira coisa que você faz:
getData(req.body.picture[0]);

Isso pode até funcionar sem ter que modificar seu onDrop rotina do que você tem. E se this.state.attachments não tem nada, seu SomeStore.state.attachments definitivamente deveria, supondo que você tenha isso salvo em uma pasta chamada stores como someStore.jsx .
import Reflux from 'reflux'
import Actions from '~/actions/actions`

class SomeStore extends Reflux.Store
{
    constructor()
    {
        super();
        this.state = {
            attachments: [],
        };
        this.listenables = Actions;
        this.baseState = {
            attachments: [],
        };
    }

    onUpdateFields(name, value) {
        this.setState({
            [name]: value,
        });
    }

    onResetFields() {
        this.setState({
           attachments: [],
        });
    }
}
const reqformdata = new SomeStore

export default reqformdata

Funções adicionais
errorHandler(e){
    switch (e.target.error.code) {
      case e.target.error.NOT_FOUND_ERR:
        alert('File not found.');
        break;
      case e.target.error.NOT_READABLE_ERR:
        alert('File is not readable.');
        break;
      case e.target.error.ABORT_ERR:
        break;    // no operation
      default:
        alert('An error occurred reading this file.');
        break;
    }
  }

progressHandler(e) {
    if (e.lengthComputable){
      const loaded = Math.round((e.loaded / e.total) * 100);
      let zeros = '';

      // Percent loaded in string
      if (loaded >= 0 && loaded < 10) {
        zeros = '00';
      }
      else if (loaded < 100) {
        zeros = '0';
      }

      // Display progress in 3-digits and increase bar length
      document.getElementById("progress").textContent = zeros + loaded.toString();
      document.getElementById("progressBar").style.width = loaded + '%';
    }
  }

E minha marcação DropZone e indicador de progresso aplicável:
render(){

const dropZoneStyle = {
  height: "34px",
  width: "300px",
  border: "1px solid #ccc",
  borderRadius: "4px",
};

return (
  <Form>
    <Col xs={5}>
            <DropZone type="file" id="docDZ"
              onDrop={this.uploadFile}
              onDropRejected={this.onDropRejected}
              onClick={this.handleUploadClick}
              onChange={this.handleChange}
              onDragEnter={this.handleDragEnter}
              onDragLeave={this.handleDragLeave}
              accept=".doc, .docx, .gif, .png, .jpg, .jpeg, .pdf"
              multiple="true"
              maxSize={999000}
              style={dropZoneStyle}>
               {'Click HERE to upload or drop files here...'}
            </DropZone>
            <table id="tblProgress">
              <tbody>
                <tr>
                  <td><b><span id="progress">000</span>%</b> <span className="progressBar"><span id="progressBar" /></span></td>
                </tr>
              </tbody>
            </table>
          </Col>
      </Row>
    </Form>
    )
  } // close render
}  // close class

E CSS:
.progressBar {
  background-color: rgba(255, 255, 255, .1);
  width: 100%;
  height: 26px;
}
#progressBar {
  background-color: rgba(87, 184, 208, .5);
  content: '';
  width: 0;
  height: 26px;
}

Outras funções que você está perdendo:
handleUploadClick(){
  return this.state;
}

handleChange(){
  this.state.errors.fileError = "";
}

handleDragEnter(event){
  event.preventDefault();
  document.getElementById("docDZ").classList.add("dragover");
}

handleDragLeave(event){
  event.preventDefault();
  document.getElementById("docDZ").classList.remove("dragover");
}

onDropRejected(files){
    const errors ={}
    let isAlertVisible = false;

    for(let i=0, j = files.length; i < j; i++){
      const file = files[i];
      const ext = file.name.split('.').pop().toLowerCase();
      //console.log(ext)

     if(this.isFileTypeValid(ext)===false){
        errors.fileError = "Only image files (JPG, GIF, PNG), Word files (DOC, DOCX), and PDF files are allowed.";
        isAlertVisible = true;
     }

     if(ext === "docx" || ext ==="gif" || ext ==="png" || ext ==="jpg" || ext ==="jpeg" || ext ==="pdf" || ext ==="doc" && file.size > 999000){
      errors.fileError = "Exceeded File Size limit! The maximum file size for uploads is 999 KB.";
      isAlertVisible = true;
    }

    this.setState({
      "errors": errors,
      "isAlertVisible": isAlertVisible,
    })
  }
}