Во внешнем интерфейсе есть функция, которая обрабатывает загрузку файла и отправляет его на серверную часть для обработки. Затем бэкэнд возвращает json, который следует использовать для обновления моего состояния React. Я настроил тестовый вызов с помощью axios.get()
, который работает нормально, когда серверная часть передает строку, отображаемую на веб-странице. console.info()
также отлично работает в этой тестовой функции. Однако когда дело доходит до моей функции uploadDoc
, console.info()
не запускается и состояние не обновляется. Вот мой код:
Приложение.js
const documentUploadHandler = ({files}) => {
const [file] = files;
uploadDoc(file);
};
const uploadDoc = async (document) => {
console.info(doc_type)
document.preventDefault();
let formData = new FormData();
formData.append('document', document);
try {
const response = await axios.post('https://127.0.0.1:8000/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
setDocType([response.data.classification]);
console.info("hello")
console.info(response.data);
} catch (error) {
console.info('Error uploading file:', error);
}
};
Сервер.py
@app.route('/api/upload', methods=['POST', 'GET'])
@cross_origin(supports_credentials=True)
def upload_file():
global class_result
if request.method == 'POST':
try:
file = request.files['document']
print(f"Uploading document {file.filename}")
filename = secure_filename(file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(file_path)
class_result = classify_document("model5", file_path)
return jsonify({"status": "get_success", "classification": class_result})
except Exception as e:
print(f"Couldn't upload document: {e}")
return jsonify({"status": "failed", "error": str(e)})
return jsonify({"status": "post_success", "classification": class_result})
Я попытался выполнить вызов API в Postman, который, как ни странно, дает мне статус успеха только тогда, когда я делаю запрос GET, а не запрос POST. Я не уверен, имеет ли это отношение к моей проблеме. Я проверил с помощью инструментов разработки на вкладке «Сеть», и он дал мне код состояния 200 и сказал, что мой метод запроса — POST, поэтому, похоже, он использует правильный тип запроса в Интернете.
Я также попробовал обновить состояние в отдельной функции с помощью axios.get()
. Это работает в том смысле, что новое состояние отображается, но только после того, как я обновлю страницу. Однако мне нужно, чтобы состояние обновлялось, как только серверная часть завершит обработку файла, поэтому я пытаюсь обновить состояние после моего вызова axios.post()
.
🤔 А знаете ли вы, что...
С Python можно создавать настольные приложения с использованием библиотеки Tkinter.
Короче говоря, axios.post
создает обещание, а не реальную ценность. Обещание — это то, что необходимо правильно обработать, когда обещание выполнено (поскольку это асинхронный вызов). Обычно с .then((r)=>{setState(r)});
Итак, для вашего случая этого должно быть достаточно:
axios.post('https://127.0.0.1:8000/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then((response)=>{
setDocType([response.data.classification]);
console.info("hello")
console.info(response.data);
})
.catch(err => {
// Handle errors
console.error(err);
});
Пример реализации компонента, обратите внимание на анализ json, это применимо только в том случае, если они на самом деле являются результатами json:
export default function UploadFiles() {
const [files, setFiles] = useState<File[]>([]);
const filesRef = useRef(null);
filesRef.current = files;
const [backendAnswer, setBackendAnswer] = useState<any>();
const handleFileSelect = useCallback((event: ChangeEvent<HTMLInputElement>) => {
if (event.target.files.length === 0) setFiles([]);
else setFiles([...event.target.files]);
}, []);
const uploadFiles = useCallback(() => {
if (filesRef.current.length != 1) return;
let formData = new FormData();
formData.append('document', filesRef.current[0]);
axios.post('https://127.0.0.1:8000/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then((response) => {
if (!response.ok) throw new Error("Error in request at " + url);
else return response.json();
}).then((jsonParsedResponse)=>{
console.info(jsonParsedResponse)
setBackendAnswer(jsonParsedResponse);
}).catch((error) => { console.error(error) });
}, []);
return <>
<div className = "flex flex-col">
<label
htmlFor = "fileUpload"
>
Select files
<input
id = "fileUpload"
name = "fileUpload"
type = "file"
className = "hidden"
onChange = {handleFileSelect}
/>
</label>
</div>
<button onClick = {uploadFiles} >Upload</button>
</>
}