[英]Having trouble writing form input to a seperate file in Javascript, Node.js, React.js, Next.js
I have been having a tough time writing form input to a seperate file in Javascript.我一直很难将表单输入写入 Javascript 中的单独文件。 I posted a repo with a demo I set up to show the problem I have been having.
我发布了一个带有演示的 repo,我设置了一个演示来显示我一直遇到的问题。 Feel free to take a look.
随意看看。 https://github.com/projectmikey/projectmikey-cant-write-to-api-dir-stackoverflow
https://github.com/projectmikey/projectmikey-cant-write-to-api-dir-stackoverflow
The app works fine locally from both "next dev" and "next start" when I end up at a http://localhost:3000 url.当我最终到达 http://localhost:3000 url 时,该应用程序从“下一个开发”和“下一个开始”在本地都可以正常工作。
My api at pages/api/demos/index.js
responds with the body from the form's textarea at the pages/new
page and writes it as a new file at / api/newfiles/file
(which becomes essentially a script file that doesnt have an extension.) This is perfect, however, I cant seem to get the file written to the /api/newfiles
folder (or any other folder for that matter with fs.writeFileSync) when I am deployed live to Vercel.我在
pages/api/demos/index.js
上的 api 在 pages pages/new
页面的表单文本区域中响应正文,并将其作为新文件写入 / api/newfiles/file
(它本质上变成了一个脚本文件,没有扩展名。)这是完美的,但是,当我实时部署到 Vercel 时,我似乎无法将文件写入/api/newfiles
文件夹(或与 fs.writeFileSync 相关的任何其他文件夹)。
I was also hoping to use shell-js to fire off a shell script ( script.sh
) So with this not working I have really been banging my head around trying to figure it out!我还希望使用 shell-js 来触发 shell 脚本(
script.sh
)所以由于这个不起作用,我真的一直在努力解决这个问题!
I am not an expert by any means at debugging the console log, but if I had to guess i would say it looks like there is http 400 error that is causing the problem while deployed with Vercel.在调试控制台日志方面,我无论如何都不是专家,但如果我不得不猜测,我会说它看起来像 http 400 错误导致使用 Vercel 部署时出现问题。
here are the key files这是关键文件
pages/api/demos/index.js
import dbConnect from '../../../lib/dbConnect'
import Demo from '../../../models/Demo'
import fs from 'fs'
import shell from "shelljs";
export default async function handler(req, res) {
const {
method,
body,
} = req
await dbConnect()
switch (method) {
case 'GET':
try {
const demos = await Demo.find({})
res.status(200).json({ success: true, data: demos })
} catch (error) {
res.status(400).json({ success: false })
}
break
case 'POST':
try {
fs.writeFileSync('api/newfiles/file', body.fileBody);
shell.exec('chmod +x ./script.sh && ./script.sh');
const demo = await Demo.create(
req.body
)
res.status(201).json({ success: true, data: demo })
} catch (error) {
res.status(400).json({ success: false })
}
break
default:
res.status(400).json({ success: false })
break
}
}
pages/api/demos/[id].js
import dbConnect from '../../../lib/dbConnect'
import Demo from '../../../models/Demo'
export default async function handler(req, res) {
const {
query: { id },
method,
} = req
await dbConnect()
switch (method) {
case 'GET' /* Get a model by its ID */:
try {
const demo = await Demo.findById(id)
if (!demo) {
return res.status(400).json({ success: false })
}
res.status(200).json({ success: true, data: demo })
} catch (error) {
res.status(400).json({ success: false })
}
break
case 'PUT' /* Edit a model by its ID */:
try {
const demo = await Demo.findByIdAndUpdate(id, req.body, {
new: true,
runValidators: true,
})
if (!demo) {
return res.status(400).json({ success: false })
}
res.status(200).json({ success: true, data: demo })
} catch (error) {
res.status(400).json({ success: false })
}
break
case 'DELETE' /* Delete a model by its ID */:
try {
const deletedDemo = await Demo.deleteOne({ _id: id })
if (!deletedDemo) {
return res.status(400).json({ success: false })
}
res.status(200).json({ success: true, data: {} })
} catch (error) {
res.status(400).json({ success: false })
}
break
default:
res.status(400).json({ success: false })
break
}
}
pages/new
import Form from '../components/Form'
const New = () => {
const demoForm = {
fileBody: [],
}
return <Form formId="add-demo-form" demoForm={demoForm} />
}
export default New
components/Form.js
import { useState } from 'react'
import { useRouter } from 'next/router'
import { mutate } from 'swr'
const Form = ({ formId, demoForm, forNewDemo = true }) => {
const router = useRouter()
const contentType = 'application/json'
const [errors, setErrors] = useState({})
const [message, setMessage] = useState('')
const [form, setForm] = useState({
fileBody: demoForm.fileBody,
})
/* The PUT method edits an existing entry in the mongodb database. */
const putData = async (form) => {
const { id } = router.query
try {
const res = await fetch(`/api/demos/${id}`, {
method: 'PUT',
headers: {
Accept: contentType,
'Content-Type': contentType,
},
body: JSON.stringify(form),
})
// Throw error with status code in case Fetch API req failed
if (!res.ok) {
throw new Error(res.status)
}
const { data } = await res.json()
mutate(`/api/demos/${id}`, data, false) // Update the local data without a revalidation
router.push('/')
} catch (error) {
setMessage('Failed to update')
}
}
/* The POST method adds a new entry in the mongodb database. */
const postData = async (form) => {
try {
const res = await fetch('/api/demos', {
method: 'POST',
headers: {
Accept: contentType,
'Content-Type': contentType,
},
body: JSON.stringify(form),
})
// Throw error with status code in case Fetch API req failed
if (!res.ok) {
throw new Error(res.status)
}
router.push('/')
} catch (error) {
setMessage('')
}
}
const handleChange = (e) => {
const target = e.target
const value =
target.name === 'poddy_trained' ? target.checked : target.value
const name = target.name
setForm({
...form,
[name]: value,
})
}
/* Makes sure demo info is filled for demo name, owner name, species, and image url*/
const formValidate = () => {
let err = {}
if (!form.fileBody) err.fileBody = 'Function is required'
return err
}
const handleSubmit = (e) => {
e.preventDefault()
const errs = formValidate()
if (Object.keys(errs).length === 0) {
forNewDemo ? postData(form) : putData(form)
} else {
setErrors({ errs })
}
}
return (
<>
<form id={formId} onSubmit={handleSubmit}>
<textarea
name="fileBody"
value={form.fileBody}
onChange={handleChange}
/>
<button type="submit" className="btn">
Submit
</button>
</form>
<div>
{Object.keys(errors).map((err, index) => (
<li key={index}>{err}</li>
))}
</div>
</>
)
}
export default Form
script.sh
#!/bin/bash
set -euo pipefail
echo "new file contents of /api/newfiles/file : $(cat ./api/newfiles/file)"
and here is the repo posted again https://github.com/projectmikey/projectmikey-cant-write-to-api-dir-stackoverflow这是再次发布的回购https://github.com/projectmikey/projectmikey-cant-write-to-api-dir-stackoverflow
thanks in advances for any help y'all...提前感谢大家的帮助...
I don't think that you can write on vercels servers我不认为你可以在 vercels 服务器上写
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.