目的是- ->在api/fileupload.js文件中生成签名的url,以便将文件上传到GCS。->通过nextjsAPI从Nextjs服务器获取签名API - localhost://3000/api/fileupload ->使用index.jsx文件中生成的签名URL将文件上传到gcs
已成功生成签名URL。但是当将图像主体作为表单数据上传到GCS时,发生403代码错误。这是响应体。
body : (...)
bodyUsed : false
headers :
Headers {}
ok : false
redirected : false
status : 0
statusText : ""
type : "opaque"
url : ""
在index.jsx文件中上传文件作为表单数据的方法是否正确?还是我错过了什么
两个文件如下所示-
nextjs文件的index.jsx-
import { useState } from "react";
export default function Home() {
const [url, setUrl] = useState("");
const [file, setFile] = useState<any>(null);
const [dataloaded, setDataloaded] = useState(true);
const handleSubmit = async (e: any) => {
setDataloaded(false);
e.preventDefault();
let formData = new FormData();
formData.append("file", file.data);
formData.append("Content-Type", `${file.data.type}`);
console.log(file);
const response = await fetch("http://localhost:3000/api/fileupload", {
method: "POST",
body: formData
});
const responseWithBody = await response.json();
console.log(responseWithBody);
setDataloaded(true);
if (response.status === 200) {
setUrl(responseWithBody.url);
} else {
console.log("error in generating url");
}
const response1 = await fetch(
responseWithBody.url,
{
mode: "no-cors",
method: "POST",
body: formData,
headers: {
"Access-Control-Allow-Origin": "*",
"content-type": "image/png"
}
}
);
console.log(response1);
};
const handleFileChange = (e: any) => {
const img = {
preview: URL.createObjectURL(e.target.files[0]),
data: e.target.files[0]
};
setFile(img);
};
return (
<>
<div className="form-container">
<form onSubmit={handleSubmit}>
<div className="image-preview-container">
{file ? (
<img src={file.preview} alt="File to upload" />
) : (
<img
src="https://raw.githubusercontent.com/koehlersimon/fallback/master/Resources/Public/Images/placeholder.jpg"
alt="Fallback"
/>
)}
</div>
<div className="file-name">
{file && file.data.name}
{url && (
<a href={url} target="_blank" rel="noreferrer">
FiExternalLink
</a>
)}
</div>
<input
type="file"
name="file"
onChange={handleFileChange}
className="custom-file-input"
></input>
<button
className="submit-button"
type="submit"
disabled={!file}
onClick={handleSubmit}
>
Submit
</button>
</form>
</div>
</>
);
}
fileupload.js在API/文件夹-
import { Storage } from "@google-cloud/storage";
import multer from "multer";
import type { NextApiRequest, NextApiResponse } from "next";
const storage = new Storage({
keyFilename: `service_account_key.json`,
projectId: "my-project-id"
});
const bucketName = "my-bucket-name";
async function parseFormData(
req: NextApiRequest & { files?: any },
res: NextApiResponse
) {
const storage = multer.memoryStorage();
const multerUpload = multer({ storage });
const multerFiles = multerUpload.any();
await new Promise((resolve, reject) => {
multerFiles(req as any, res as any, (result: any) => {
if (result instanceof Error) {
return reject(result);
}
return resolve(result);
});
});
return {
fields: req.body,
files: req.files
};
}
export default async function handler(
req: NextApiRequest & { files?: any },
res: NextApiResponse<any>
) {
const options = {
version: "v4",
action: "write",
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
contentType: "application/octet-stream"
} as any;
const result = await parseFormData(req, res);
// console.log(result);
const file = storage
.bucket(bucketName)
.file(result?.files[0]?.originalname || "new-file.png");
const [url]: any = await file.getSignedUrl(options);
console.log("Generated PUT signed URL:");
console.log(url);
res.status(200).json({ url: url });
}
1条答案
按热度按时间wwwo4jvm1#
我想发送原始文件的名称,在该文件上将生成一个签名的URL,并使用Nextjs GET API接收该签名的URL。
下面是解决方案代码-在API/fileupload.ts中
通过Nextjs GET API获得签名的URL,并使用签名的URL、从事件的目标对象保存的数据以及标头中的实际内容类型调用PUT API。
index.jsx文件-