我有一个react前端,可以使用express将数据发送到postgres后端,我使用javascript的FileReader()从前端上传了一个pdf文件,大小为779字节,作为一个字节数组(U8intArray),字节被插入到数据库的bytea类型的表列中。
当FileReader()运行时,我的应用会将文件的数据缓冲区记录到控制台。控制台会显示文件具有以下起始字节:
(779)[37, 80, 68, 70, 45, 49, 46, ... ]
我可以从终端使用下面的sql查询来验证这些字节是否确实存储到了我的数据库中:
select left(encode(my_file, 'escape'), 50) from apps where id = 24;
终端输出:
left
----------------------------------------------------
{"0":37,"1":80,"2":68,"3":70,"4":45,"5":49,"6":46,
(1 row)
但问题是:当我的前端尝试从postgress检索这个字节数组数据时,字节看起来与我插入的内容不同:
// the id used is 24
axios.get("/api/get/app", { params: { id } }).then((res) => {
console.log(res.data.my_file.data);
})
控制台输出:
(7136)[123, 34, 48, 34, 58, 51, 55, ... ]
它有7136个字节。我期望原始的[37,80,68,70,45,49,46,...]有779个字节。
当我从不同的行检索不同的pdf数据时,控制台将输出一个类似的数组,该数组再次以与上一次尝试相同的[123,34,48,34,58,51,55,...]开头,但总字节数不同,如147990。
我使用的post/get请求结构和其他类型的数据一样,比如字符串和数字,它们在前端工作得很好。但是对于bytea数据,返回到前端的输出和我输入的不一样。当我检索bytea数据时,格式必须有一些变化。
- 因此问题是,如何检索插入的bytea数据并将其转换为原始的Uint8Array格式?**
至于代码,我的数据库中有一个名为apps的表,它存储了工作申请数据字段,其中的列包括公司名称、申请日期和简历。
//front end code to retrieve data from database
const { id } = useParams();
const context = useContext(Context);
const [postingURL, setPostingURL] = useState("");
const [companyName, setCompanyName] = useState("");
const [jobTitle, setJobTitle] = useState("");
const [jobDescription, setJobDescription] = useState("");
const [jobNotes, setJobNotes] = useState("");
const [tags, setTags] = useState("");
const [appDate, setAppDate] = useState();
const [elapsedDays, setElapsedDays] = useState(0);
const [careersList, setCareersList] = useState([""]);
const [careerNum, setCareerNum] = useState(0);
const [newCareerNum, setNewCareerNum] = useState();
const [resumeBytea, setResumeBytea] = useState();
const [coverLetterBytea, setCoverLetterBytea] = useState([]);
useEffect(() => {
if (context.isAuthenticated && context.dbProfileState) {
axios
.get("/api/get/app", { params: { id } })
.then((res) => {
setPostingURL(res.data.posting_url);
setCompanyName(res.data.company_name);
setJobTitle(res.data.job_title);
setJobDescription(res.data.job_description);
setJobNotes(res.data.job_notes);
setTags(String(res.data.tags));
setCareerNum(
newCareerNum >= 0
? newCareerNum
: dbProfile.careers_list.indexOf(res.data.career_name)
);
let appDate = new Date(res.data.application_date);
let currDate = new Date();
let elapsed =
Math.ceil((currDate - appDate) / (1000 * 3600 * 24)) - 1;
setAppDate(appDate);
setElapsedDays(elapsed);
setResumeBytea(res.data.resume_file)
// console.log(res.data.resume_file)
setCoverLetterBytea(res.data.cover_letter_file.data);
})
.catch((err) => console.log(err));
}
}, [context, id]);
}
//back end express/node code to send table row data to front end
router.get("/api/get/app", (req, res) => {
const appId = req.query.id;
pool.query(
`SELECT * FROM apps WHERE app_id = $1`,
[appId],
(q_err, q_res) => {
res.json(q_res.rows[0]);
}
);
console.log("Queried row id:", appId);
});
表格结构:
CREATE TABLE apps (
app_id SERIAL UNIQUE,
username TEXT UNIQUE REFERENCES users(username),
career_name TEXT,
posting_url TEXT,
company_name TEXT NOT NULL,
job_title TEXT NOT NULL,
job_description TEXT,
job_notes TEXT,
resume_file BYTEA,
cover_letter_file BYTEA,
tags TEXT [],
application_date TEXT,
PRIMARY KEY(app_id)
);
1条答案
按热度按时间t3psigkw1#
好吧,我知道了。
postgres中的bytea数据是二进制格式的,在发送之前需要从后端将其编码为文本格式。
因此,不要使用
SELECT *
sql查询发送整行,如下所示:我必须修改sql查询以使用encode()函数,如下所示:
然后,前端将接收解析的数据对象“res”,其中行数据的res.data.resume_file部分将是一个字符串,如下所示:
然后需要使用JSON.parse()将其转换为一个对象,然后将其转换为一个数组,再转换为一个Uint8Array,如下所示: