gpt4 book ai didi

javascript - NodeJS/重新验证 : How can I recieve file upload in API?

转载 作者:数据小太阳 更新时间:2023-10-29 04:53:08 27 4
gpt4 key购买 nike

我正在尝试从移动应用程序(用 React Native 编写,现在在 iOS 上运行)上传图像文件。

文件被发送到我的 REST API,如下所示。我遇到了两个问题:

  1. 我没有得到 req.body,因为它始终是一个空对象,尽管 header 已正确提交。
  2. 我想通过 gridfs-stream 将收到的文件写入我的数据库 (GridFS),但我不知道该把代码放在哪里。

API

const restify = require('restify')
const winston = require('winston')
const bunyanWinston = require('bunyan-winston-adapter')
const mongoose = require('mongoose')
const Grid = require('gridfs-stream')
const config = require('../config')

// Configure mongoose to work with javascript promises
mongoose.Promise = global.Promise

// Setting up server
const server = restify.createServer({
name: config.name,
version: config.version,
log: bunyanWinston.createAdapter(log)
})

server.use(restify.plugins.multipartBodyParser())

server.listen(config.port, () => {
mongoose.connection.on('open', (err) => {
server.post('/upload', (req, res, next) => {
console.log(req.headers) // <- returns headers as expected

/* Problem 1 */
console.log(req.body) // <- is empty object (unexpected)
res.send(200, { message: 'successful upload' })
res.end()
})
})

global.db = mongoose.connect(config.db.uri, { useMongoClient: true })

/* Problem 2: The recieved file should be stored to DB via `gridfs-stream` */
// I think this is the wrong place for this line...
var gfs = Grid(global.db, mongoose.mongo)
})

我试图找出错误,但没有找到,所以这里是我在 API 中获得的数据:

标题

{ 
host: 'localhost:3000',
'content-type': 'multipart/form-data; boundary=pUqK6oKvY65OfhaQ3h01xWg0j4ajlanAA_e3MXVSna4F8kbg-zT0V3-PeJQm1QZ2ymcmUM',
'user-agent': 'User/1 CFNetwork/808.2.16 Darwin/15.6.0',
connection: 'keep-alive',
accept: '*/*',
'accept-language': 'en-us',
'accept-encoding': 'gzip, deflate',
'content-length': '315196'
}

正文

{ }

为什么 body 是空的?


React Native 文件上传

这就是我将文件发送到 API 的方式。我还向您展示了一些变量的内容:

async function upload (photo) {
console.log('photo', photo); // OUTPUT SHOWN BELOW
if (photo.uri) {
// Create the form data object
var data = new FormData()
data.append('picture', { uri: photo.uri, name: 'selfie.jpg', type: 'image/jpg' })

// Create the config object for the POST
const config = {
method: 'POST',
headers: {
'Accept': 'application/json'
},
body: data
}
console.log('config', config); // OUTPUT SHOWN BELOW

fetchProgress('http://localhost:3000/upload', {
method: 'post',
body: data
}, (progressEvent) => {
const progress = progressEvent.loaded / progressEvent.total
console.log(progress)
}).then((res) => console.log(res), (err) => console.log(err))
}
}

const fetchProgress = (url, opts = {}, onProgress) => {
console.log(url, opts)
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.open(opts.method || 'get', url)
for (var k in opts.headers || {}) {
xhr.setRequestHeader(k, opts.headers[k])
}
xhr.onload = e => resolve(e.target)
xhr.onerror = reject
if (xhr.upload && onProgress) {
xhr.upload.onprogress = onProgress // event.loaded / event.total * 100 ; //event.lengthComputable
}
xhr.send(opts.body)
})
}

照片

{
fileSize: 314945,
origURL: 'assets-library://asset/asset.JPG?id=106E99A1-4F6A-45A2-B320-B0AD4A8E8473&ext=JPG',
longitude: -122.80317833333334,
fileName: 'IMG_0001.JPG',
height: 2848,
width: 4288,
latitude: 38.0374445,
timestamp: '2011-03-13T00:17:25Z',
isVertical: false,
uri: 'file:///Users/User/Library/Developer/CoreSimulator/Devices/D3FEFFA8-7446-42AB-BC7E-B6EB88DDA840/data/Containers/Data/Application/17CE8C0A-B781-4E56-9347-857E74055119/Documents/images/69C2F27F-9EEE-4611-853E-FC7FF6E5C373.jpg'
}

配置

'http://localhost:3000/upload', 
{
method: 'post',
body:
{
_parts:
[
[ 'picture',
{ uri: 'file:///Users/User/Library/Developer/CoreSimulator/Devices/D3FEFFA8-7446-42AB-BC7E-B6EB88DDA840/data/Containers/Data/Application/17CE8C0A-B781-4E56-9347-857E74055119/Documents/images/69C2F27F-9EEE-4611-853E-FC7FF6E5C373.jpg',
name: 'selfie.jpg',
type: 'image/jpg' }
]
]
}
}

我认为 data(应该在 config 中作为 body 发送)格式错误。为什么数组中有数组?

最佳答案

下面的例子使用了react-native-fetch-blob在 React Native 部分,以及带有 Express 和 Formidable 的 Nodejs在服务器端解析表单。

让我们先在确定用户上传的是照片还是视频后上传文件:

RNFetchBlob.fetch(
'POST',
Constants.UPLOAD_URL + '/upload',
{
'Content-Type': 'multipart/form-data'
},
[
{
name: this.state.photoURL ? 'image' : 'video',
filename: 'avatar-foo.png',
type: 'image/foo',
data: RNFetchBlob.wrap(dataPath)
},
// elements without property `filename` will be sent as plain text
{ name: 'email', data: this.props.email },
{ name: 'title', data: this.state.text }
]
)
// listen to upload progress event
.uploadProgress((written, total) => {
console.log('uploaded', written / total);
this.setState({ uploadProgress: written / total });
})
// listen to download progress event
.progress((received, total) => {
console.log('progress', received / total);
})
.then(res => {
console.log(res.data); // we have the response of the server
this.props.navigation.goBack();
})
.catch(err => {
console.log(err);
});
};

同样,接收文件并相应地加载数据:

exports.upload = (req, res) => {
var form = new formidable.IncomingForm();
let data = {
email: '',
title: '',
photoURL: '',
videoURL: '',
};

// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = path.join(__dirname, '../../uploads');

form.on('file', (field, file) => {
let suffix = field === 'image' ? '.png' : '.mp4';
let timestamp = new Date().getTime().toString();

fs.rename(file.path, path.join(form.uploadDir, timestamp + suffix)); //save file with timestamp.

data[field === 'image' ? 'photoURL' : 'videoURL'] = timestamp + suffix;
});
form.on('field', (name, value) => {
data[name] = value;
});
form.on('error', err => {
console.log('An error has occured: \n ' + err);
});
form.on('end', () => {
// now we have a data object with fields updated.
});
form.parse(req);
};

并使用 Controller 函数:

let route = express.Router();
// other controller functions...
route.post('/upload', uploadController.upload);
app.use(route);

请务必阅读代码中包含的注释。 Datapath 是在使用 react-native-image-picker 后创建的媒体路径(不是 base64 字符串) .您可以使用 react-native-progress显示上传进度。

查看 react-native-fetch-blob 的 multipartform-data 部分以供进一步引用:https://github.com/wkh237/react-native-fetch-blob#multipartform-data-example-post-form-data-with-file-and-data

关于javascript - NodeJS/重新验证 : How can I recieve file upload in API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45948918/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com