我正在使用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执行定期查询,询问此文件是否已上传,直到成功上传?谢谢