загрузка axios в API node.js приводит к тому, что файлы в aws s3 становятся нечитаемыми - PullRequest
0 голосов
/ 06 июля 2018

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

серверный JavaScript;

var express = require("express");
var mongodb = require("mongodb");
var _ = require("lodash");
var bodyParser = require("body-parser");
var app = express();
var router = express.Router();
var mongoose = require("mongoose");
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-1'});
var s3 = new AWS.S3({apiVersion: '2006-03-01'});

...
...
...

router.post('/upload', function (req, res) {
  var file = new File({name: req.body.fileName, type: req.body.contentType, buffer: req.body.file});
  var fs = require('fs');
  var fileStream = fs.createWriteStream(req.body.fileName);
  fileStream.write(req.body.file)
  fileStream.end(function () { console.log('done'); });
  fileStream.on('error', function(err) {
    console.log('File Error', err);
  });
  fs.readFile(req.body.fileName, (err, data) => {
     if (err) throw err;
     console.log(data);
     const params = {
         Bucket: req.body.crystalName,
         Key: req.body.fileName,
         Body: data
     };
     s3.upload(params, function(s3Err, data) {
         if (s3Err) {
           console.log(s3Err);
         } else {
           res.send(`File uploaded successfully at ${data.Location}`);
           console.log(`File uploaded successfully at ${data.Location}`);
         }
     });
  });
});

функция загрузки на стороне клиента (vue.js);

<template>
  <div class="main">
    <input v-model="crystalName" placeholder="Crystal Name" />
    <input type="file" @change="onFileChange"/>
    <button v-on:click="uploadToCrystal">Upload</button>
    <span>{{this.file}}</span>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'crystalviewer',
  props: ['user'],
  data: function () {
    return {
      crystalName: '',
      fileName: '',
      contentType: '',
      file: ''
    }
  },
  methods: {
    onFileChange (file) {
      let vue = this
      var reader = new FileReader()
      this.fileName = file.target.files[0].name || file.dataTransfer.files[0].name
      this.contentType = file.target.files[0].type || file.dataTransfer.files[0].type
      console.log(this.contentType)
      var start = 0
      var stop = file.target.files[0].size
      var blob = file.target.files[0].slice(start, stop)
      reader.onloadend = function (file) {
        vue.file = file.target.result
      }
      reader.readAsText(blob, 'utf-8')
    },
    uploadToCrystal () {
      let vue = this
      axios.post('https://api.mystic-crm.com/crystalviewer/upload', {
        crystalName: vue.crystalName,
        fileName: vue.fileName,
        contentType: vue.contentType,
        file: vue.file
      })
        .then(response => {
          console.log(response)
        })
        .catch(err => {
          console.log(err)
        })
    }
  }
}
</script>

<style scoped lang="less">
  .main {

  }
</style>

Чтобы получить файлы после загрузки, запустите get против;

https://api.mystic -crm.com / crystalviewer / содержание /: crystalName /: имя_файла

, где *; 1020 *

: crystalName = testcrystalmystic
: fileName = your_file_to_get

1 Ответ

0 голосов
/ 06 июля 2018

Оказалось, что переключение на Multiparty было решением, теперь я могу загружать через формы. Очевидно, axios не поддерживает загрузку файлов, но формы делают это забавным открытием. изменить добавленный рабочий интерфейс

var express = require("express");
var AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-1'});
var s3 = new AWS.S3({apiVersion: '2006-03-01'});
var multiparty = require('multiparty');

router.post('/upload', function (req, res) {
  var form = new multiparty.Form();
    var destPath;
    var crystalName;
    form.on('field', function(name, value) {
      if (name === 'crystalName') {
        crystalName = value
      } else if (name === 'fileName') {
        destPath = value;
      }
    });
    form.on('part', function(part) {
      s3.putObject({
        Bucket: crystalName,
        Key: destPath,
        ACL: 'public-read',
        Body: part,
        ContentLength: part.byteCount
      }, function(err, data) {
        if (err) throw err;
        console.log("done", data);
        res.end("OK");
        console.log("https://s3.amazonaws.com/" + crystalName + '/' + destPath);
      });
    });
    form.parse(req);
});

передняя часть от;

<template>
  <div class="main">
    <form v-on:submit="submit">
      <input name="crystalName" placeholder="Crystal Name" />
      <input name="fileName" v-model="fileName" placeholder="File Name" v-show="false" />
      <input name="file" type="file" @change="onFileChange"/>
      <input type="submit" value="Upload File" />
    </form>
  </div>
</template>

<script>
export default {
  name: 'crystalviewer',
  props: ['user'],
  data: function () {
    return {
      fileName: '',
      modal: ''
    }
  },
  methods: {
    submit (event) {
      let vue = this
      var form = document.forms[0]
      var request = new XMLHttpRequest()
      request.open('POST', 'https://api.mystic-crm.com/crystalviewer/upload', true)
      request.setRequestHeader('accept', 'multipart/form-data')
      event.preventDefault()
      var formData = new FormData(form)
      request.send(formData)
      request.onreadystatechange = function () {
        if (request.readyState < 4) {
          vue.modal = 'loading'
        } else if (request.readyState === 4) {
          if (request.status === 200 || request.status < 300) {
            vue.modal = 'success'
            console.log('success')
          } else {
            vue.modal = 'failure'
            console.log('failure')
          }
        }
      }
    },
    onFileChange (file) {
      this.fileName = file.target.files[0].name || file.dataTransfer.files[0].name
    }
  }
}
</script>

<style scoped lang="less">
  .main {

  }
</style>
...