【发布时间】:2021-01-02 18:29:25
【问题描述】:
如何使用 expo 从 React Native 上传文件(pdf、文档等)到使用 node.js 的服务器。我见过很多使用 expo image-picker api 的图像示例,但我没有遇到使用 expo 中的 document-picker 或文件系统 api 的示例。对于像我这样的初学者来说,expo 文件系统文档有点难以理解。
【问题讨论】:
标签: node.js react-native expo multer
如何使用 expo 从 React Native 上传文件(pdf、文档等)到使用 node.js 的服务器。我见过很多使用 expo image-picker api 的图像示例,但我没有遇到使用 expo 中的 document-picker 或文件系统 api 的示例。对于像我这样的初学者来说,expo 文件系统文档有点难以理解。
【问题讨论】:
标签: node.js react-native expo multer
感谢您的帮助。我想出了一个解决方案,并将其发布在下面,以便将来来这里的任何人都可以使用它。
反应原生
import React, { useState } from 'react';
import { Button, View } from 'react-native';
import * as DocumentPicker from 'expo-document-picker';
import * as FileSystem from 'expo-file-system';
const DocPicker = () => {
const [ doc, setDoc ] = useState();
const pickDocument = async () => {
let result = await DocumentPicker.getDocumentAsync({ type: "*/*", copyToCacheDirectory: true }).then(response => {
if (response.type == 'success') {
let { name, size, uri } = response;
let nameParts = name.split('.');
let fileType = nameParts[nameParts.length - 1];
var fileToUpload = {
name: name,
size: size,
uri: uri,
type: "application/" + fileType
};
console.log(fileToUpload, '...............file')
setDoc(fileToUpload);
}
});
// console.log(result);
console.log("Doc: " + doc.uri);
}
const postDocument = () => {
const url = "http://192.168.10.107:8000/upload";
const fileUri = doc.uri;
const formData = new FormData();
formData.append('document', doc);
const options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
console.log(formData);
fetch(url, options).catch((error) => console.log(error));
}
return (
<View>
<Button title="Select Document" onPress={pickDocument} />
<Button title="Upload" onPress={postDocument} />
</View>
)
};
export default DocPicker;
Node.js
const express = require('express')
const bodyParser = require('body-parser')
var multer = require('multer')
var upload = multer({ dest: 'uploads/' })
const app = express()
const fs = require('fs')
const http = require('http')
const port = 8000
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req,res) => {
res.json({
success: true
})
})
app.post('/', (req, res) => {
console.log(req.body)
res.status(200)
})
app.post('/upload', upload.single('document'),(req , res) => {
console.log(req.file, req.body)
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
干杯!!!
【讨论】:
【讨论】:
这里是一个例子,后端也使用了multer和express:https://github.com/expo/examples/tree/master/with-formdata-image-upload
也就是说,我建议使用 FileSystem.uploadAsync 而不是 fetch 和后台 sessionType,以便在应用程序在 iOS 上作为后台时支持上传。
【讨论】:
如果@Anandhu 给出的解决方案不起作用,那么试试上面这样的代码。
import React, { useState } from 'react';
import { Button, View } from 'react-native';
import * as DocumentPicker from 'expo-document-picker';
import * as FileSystem from 'expo-file-system';
const DocPicker = () => {
const [ doc, setDoc ] = useState();
const pickDocument = async () => {
let result = await DocumentPicker.getDocumentAsync({
type: "*/*",
copyToCacheDirectory: true })
.then(response => {
if (response.type == 'success') {
let { name, size, uri } = response;
/ ------------------------/
if (Platform.OS === "android" && uri[0] === "/") {
uri = `file://${uri}`;
uri = uri.replace(/%/g, "%25");
}
/ ------------------------/
let nameParts = name.split('.');
let fileType = nameParts[nameParts.length - 1];
var fileToUpload = {
name: name,
size: size,
uri: uri,
type: "application/" + fileType
};
console.log(fileToUpload, '...............file')
setDoc(fileToUpload);
}
});
// console.log(result);
console.log("Doc: " + doc.uri);
}
const postDocument = () => {
const url = "http://192.168.10.107:8000/upload";
const fileUri = doc.uri;
const formData = new FormData();
formData.append('document', doc);
const options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
};
console.log(formData);
fetch(url, options).catch((error) => console.log(error));
}
return (
<View>
<Button title="Select Document" onPress={pickDocument} />
<Button title="Upload" onPress={postDocument} />
</View>
)
};
export default DocPicker;
路径的编码方式存在错误,并且缺少 file:// 方案。
此错误可能会在下一版本中修复。
【讨论】: