大文件上传中“发布”两次呼叫

时间:2018-07-11 17:47:06

标签: file express upload axios

我正在使用React,Express和Node来处理将音频文件上传到Google Cloud存储桶的过程。它工作正常,除非音频文件> 20 mb。

这是调用post方法的反应代码:

class UploadHandlers extends React.Component{
  state = initialState;

  reset = () => {
    this.setState(initialState);
  }

  handleUpload = () => {
    var data = new FormData();
    var songFile = this.state.songUploadFields.songFile;

    data.append('songFile', songFile);
    data.append('title', this.state.songUploadFields.title);
    data.append('description', this.state.songUploadFields.description);
    data.append('genres', this.state.songUploadFields.genre);
    data.append('URL', this.state.songUploadFields.songURL);
    this.setState({isLoading: true});
    axios({
      method: 'post',
      url: 'http://localhost:8080/uploadSong',
      data: data,
      withCredentials: true
    }).then((result) => {
      //access results....
      this.reset();
    });

  }

这是快递代码:

var cloud_bucket = require('../controllers/uploadController.js');
const multer = require('multer');

const uploadSong = multer({
  storage: multer.MemoryStorage,
  fileFilter: function(req, file, cb) {
    console.log(file.mimetype);
    if(file.mimetype !== 'audio/wav' && file.mimetype !== 'audio/mpeg'){
      return cb(new Error('only wavs and mp3s are allowed'))
    }
    cb(null, true)
  }
});

module.exports = function(app){

  app.post('/uploadSong', uploadSong.single('songFile'), (req, res) => {
    cloud_bucket.uploadSong(req, res, console.log, () => res.status(200).send('ok'));
  });

这是Google云文件上传代码:

var Promise = require('bluebird');
var GoogleCloudStorage = Promise.promisifyAll(require('@google-cloud/storage'));
const uuidv4 = require('uuid/v4');


const {sequelize, Sequelize} = require('../db/dbConnect.js');
const Song = require('../models/song.js')(sequelize, Sequelize);


var storage = GoogleCloudStorage({
  projectId: 'thread-204819',
  keyFilename: './thread-projectowner.json'
});

var BUCKET_NAME = 'thread_song_bucket';

var myBucket = storage.bucket(BUCKET_NAME);

function getPublicUrl (file_name) {
  console.log(`https://storage.googleapis.com/${BUCKET_NAME}/${file_name}`)
  return `https://storage.googleapis.com/${BUCKET_NAME}/${file_name}`;
}

module.exports = {
  uploadSong: function (req, res, next, fin) {
      songFileToBucket(req, res, next, fin);
  },



songFileToBucket = (req, res, next, fin) => {
    const file = req.file;
    var url = '';
    const gcsname = uuidv4() + file.originalname;
    file2 = myBucket.file(gcsname);
    const stream = file2.createWriteStream({metadata: {contentType: file.mimetype}});
    stream.on('error', (err) => {
      file.cloudStorageError = err;
      next(err);
    });
    stream.on('finish', () => {
      file.cloudStorageObject = gcsname;
      file2.makePublic().then(() => {
        file.cloudStoragePublicUrl = getPublicUrl(gcsname);
        url = file.cloudStoragePublicUrl;
        return url;
      }).then((url) => {
        console.log('upload complete');
        songMetaToDb(req, url, res, gcsname);
        fin()
      });
    });
    stream.end(file.buffer);
}

//send metadata to mysql
songMetaToDb = (req, url, res, gcsname) => {
  Song.create({
    title: req.body.title,
    description: req.body.description,
    genres: req.body.genres,
    owner: req.session.user.idUsers,
    dateUploaded: new Date(),
    URL: url,
    fileName: gcsname,
  })
}

我省略了一些不相关的代码处理文件删除,这就是为什么语法看起来不正确的原因。

我怀疑正在发生的事情是在大量写入流中,没有来自Express的响应,而axios尝试再次发布。有时这会导致重复的文件上载,而有时会导致其中一个写流被破坏。小于〜20mb的任何东西都可以正常工作。

有什么办法可以防止这种情况?有没有一种方法可以从快递返回多个响应,例如:“收到请求,请稍候”?

还是我应该立即发送响应,并从axios执行定期查询,询问此文件是否已上传,直到成功上传?谢谢

0 个答案:

没有答案