MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Konvertieren von Blob in Binär, um es in Mongodb zu speichern

Ich denke also, Ihr Problem liegt in dieser Zeile:

new_project.picture.data = fs.readFileSync(req.body.picture[0]);

Und es ist die mongoDB-Tabellenspalte, in die Sie data einfügen in das gibt Ihnen diesen Fehler. Es erwartet einen String oder Buffer und Sie haben ihm ein File-Objekt gegeben.

Sie können eine Base64-Byte-Zeichenfolge mit was ich hier gepostet habe , die ich versuchen werde, unten in Ihren Code zu integrieren:

Sie müssen sicherstellen, dass Sie eine Variable zum Sammeln Ihrer Datei(en) haben. So habe ich den oberen Rand meiner Seite eingerichtet:

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,
    ]
    ....

Dann neue Funktionen binden:

    ....
    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

Dann arbeiten wir daran, die Bytes an attachments zu liefern und an new_project.picture.data senden . Für mich verwende ich eine Funktion, die onDrop ausführt der DropZone mit onDrop={this.uploadFile} . Ich kann nicht wirklich sagen, was Sie tun, weil ich keine Ahnung habe, was filesToUpload ist bezieht sich auf. Meine uploadFile sieht so aus:

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
  }
}

und das wäre der getData Die Funktion wurde für jede Datei ausgeführt, die in die DropZone abgelegt/hinzugefügt wurde:

getData(f) {
    const reader = new FileReader();
    reader.onerror = this.errorHandler;
    reader.onprogress = this.progressHandler;
    reader.onload = this.processFile(f);
    reader.readAsDataURL(f);
}

Dann processFile() aus dem onload läuft:

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.
  }
}

Sobald Sie das haben, sollten Sie in der Lage sein:

new_project.picture.data = this.state.attachments[0];

Wenn nicht, können Sie aus irgendeinem Grund versuchen, dies innerhalb von exports.create_a_project() aufzurufen , als erstes:

getData(req.body.picture[0]);

Dies könnte sogar funktionieren, ohne dass Sie Ihr onDrop ändern müssen Routine von dem, was Sie haben. Und wenn this.state.attachments hat nichts, Ihre SomeStore.state.attachments sollten Sie auf jeden Fall, vorausgesetzt, Sie haben dies in einem Ordner namens stores gespeichert als 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

Zusatzfunktionen

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 + '%';
    }
  }

Und meine DropZone und anwendbares Markup für die Fortschrittsanzeige:

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

Und 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;
}

Andere Funktionen, die Sie vermissen:

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,
    })
  }
}