- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 Apollo 客户端 + apollo-upload-client 在客户端和 apollo-express-server 在服务器端。
我有下一个错误:
POST body missing. Did you forget use body-parser middleware?
我确定我的服务器上有正文解析器。
Server.ts
import "reflect-metadata";
import "dotenv-safe/config";
import 'module-alias/register';
import { __prod__ } from "@/config/config";
import express from "express";
import Redis from "ioredis";
import session from "express-session";
import connectRedis from "connect-redis";
import { createConnection } from "typeorm";
import { User } from "@/entities/User";
import { Project } from "@/entities/Project";
import path from "path";
const server = async () => {
await createConnection({
type: "postgres",
url: process.env.DATABASE_URL,
logging: true,
migrations: [path.join(__dirname, "./migrations/*")],
entities: [User, Project]
});
const app = express();
require("@/start/logger"); // log exceptions
const RedisStore = connectRedis(session); // connect redis store
const redis = new Redis(process.env.REDIS_URL);
require("@/start/apolloServer")(app, redis); // create apollo server
require("@/start/appConfig")(app,redis,RedisStore) // configure app
const PORT = process.env.PORT || 3007;
app.listen(PORT, () => {
console.log(`🚀 Server Started at PORT: ${PORT}`);
});
};
server().catch((err) => {
console.error(err);
});
我的 Apollo 服务器
import { ApolloServer, gql } from "apollo-server-express";
import { buildSchema } from "type-graphql";
import ProfilePictureResolver from "@/resolvers/upload";
import { createUserLoader } from "@/utils/createUserLoader";
import { UserResolver } from "@/resolvers/user";
import { ProjectResolver } from "@/resolvers/project";
import {Express} from "express";
import { Redis } from "ioredis";
const typeDefs = gql`
scalar Upload
type File {
id: ID!
filename: String!
mimetype: String!
path: String!
}
type Mutation {
singleUpload(file: Upload!): File!
}
`;
module.exports = async function(app:Express,redis:Redis){
const apolloServer = new ApolloServer({
typeDefs,
schema: await buildSchema({
resolvers: [UserResolver, ProjectResolver, ProfilePictureResolver],
validate: false,
}),
context: ({ req, res }) => ({
req,
res,
redis,
userLoader: createUserLoader()
}),
uploads: false
});
apolloServer.applyMiddleware({
app,
cors: false,
});
}
解析器:
import { Resolver, Mutation, Arg } from 'type-graphql'
import { GraphQLUpload, FileUpload } from 'graphql-upload'
import os from 'os'
import { createWriteStream } from 'fs'
import path from 'path'
@Resolver()
export default class SharedResolver {
@Mutation(() => Boolean)
async uploadImage(
@Arg('file', () => GraphQLUpload)
file: FileUpload
): Promise<Boolean> {
const { createReadStream, filename } = await file
const destinationPath = path.join(os.tmpdir(), filename)
const url = await new Promise((res, rej) =>
createReadStream()
.pipe(createWriteStream(destinationPath))
.on('error', rej)
.on('finish', () => {
//stuff to do
})
);
return true;
}
}
服务器配置
import {Express} from 'express'
import { __prod__, COOKIE_NAME } from "@/config/config";
import cors from "cors";
import session from "express-session";
import { Redis } from 'ioredis';
import { RedisStore } from 'connect-redis';
import { bodyParserGraphQL } from 'body-parser-graphql'
module.exports = function(app:Express, redis:Redis, RedisStore:RedisStore){
app.set("trust proxy", 1);
app.use(bodyParserGraphQL());
app.use(
cors({
origin: process.env.CORS_ORIGIN,
credentials: true,
})
);
app.use(
session({
name: COOKIE_NAME,
store: new RedisStore({
client: redis,
disableTouch: true,
}),
cookie: {
maxAge: 1000 * 60 * 60 * 24 * 365 * 10, // 10 years
httpOnly: true,
sameSite: "lax",
secure: __prod__,
domain: __prod__ ? ".heroku.com" : undefined,
},
saveUninitialized: false,
secret: process.env.SESSION_SECRET,
resave: false,
})
);
}
客户端
应用客户端
import { createWithApollo } from "@/utils/createWithApollo";
import { ApolloClient, InMemoryCache } from "@apollo/client";
import { NextPageContext } from "next";
import { createUploadLink } from 'apollo-upload-client';
const createClient = (ctx: NextPageContext) =>
new ApolloClient({
credentials: "include",
headers: {
cookie:
(typeof window === "undefined"
? ctx?.req?.headers.cookie
: undefined) || "",
},
cache: new InMemoryCache({
typePolicies: {
Query: {}
}
}),
link: createUploadLink({uri:'http://localhost:4000/graphql'})
});
// const createClient: ApolloClient<NormalizedCacheObject> = new ApolloClient({
// cache: new InMemoryCache({}),
// uri: 'http://localhost:4000/graphql'
// });
export const withApollo = createWithApollo(createClient);
查询
import { gql } from '@apollo/client';
export const UPLOAD_IMAGE_MUTATION = gql`
mutation uploadImage($file: Upload!) {
uploadImage(file: $file)
}
`;
页面
import React, {useState} from 'react';
import {useSelector} from "react-redux";
import {Box} from "@/components/UI/Box/Box"
import {Header} from "@/components/UI/Text/Header"
import { withApollo } from "@/utils/withApollo";
import withPrivateRoute from "@/HOC/withPrivateRoute";
import { useMutation } from "@apollo/react-hooks";
import { UPLOAD_IMAGE_MUTATION } from "@/graphql/mutations/uploadImage";
interface IProps{};
const Profile:React.FC<IProps> = () => {
const user = useSelector(state => state.user);
const [file, setFileToUpload] = useState(null);
const [uploadImage, {loading}] = useMutation(UPLOAD_IMAGE_MUTATION);
const onAvatarUpload = (e) =>{
setFileToUpload(e.target.files[0]);
}
const onSubmit = async (e) =>{
e.preventDefault();
const response = await uploadImage({
variables: {file}
});
}
return (
<Box mt={20} pl={30} pr={30}>
<Header>
Edit Profile
</Header>
<input onChange={onAvatarUpload} type="file" placeholder="photo" />
<button onClick={(e)=>onSubmit(e)}>Submit</button>
</Box>
)
};
export default withApollo({ ssr: false })(withPrivateRoute(Profile, true));
我的客户端包:
{
"name": "app",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@apollo/client": "^3.2.5",
"@apollo/react-hooks": "^4.0.0",
"apollo-upload-client": "^14.1.3",
"graphql": "^15.4.0",
"graphql-tag": "^2.11.0",
"graphql-upload": "^11.0.0",
"isomorphic-unfetch": "^3.1.0",
"next": "^9.5.5",
"next-apollo": "^5.0.3",
"next-redux-wrapper": "^6.0.2",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-is": "^16.13.1",
"react-redux": "^7.2.2",
"redux": "^4.0.5",
"styled-components": "^5.2.1",
"urql": "^1.10.3",
"uuid": "^8.3.1"
},
"devDependencies": {
"@testing-library/jest-dom": "^5.11.5",
"@testing-library/react": "^11.1.1",
"@types/graphql": "^14.5.0",
"@types/jest": "^26.0.15",
"@types/next": "^9.0.0",
"@types/node": "^14.0.27",
"@types/react": "^16.9.55",
"@types/react-dom": "^16.9.9",
"@types/styled-components": "^5.1.4",
"@types/uniqid": "^5.2.0",
"@types/uuid": "^8.3.0",
"@welldone-software/why-did-you-render": "^5.0.0",
"babel-plugin-inline-react-svg": "^1.1.2",
"babel-plugin-module-resolver": "^4.0.0",
"babel-plugin-styled-components": "^1.11.1",
"redux-devtools-extension": "^2.13.8",
"typescript": "^4.0.5"
}
}
服务器包:
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "server.ts",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"nodemon": "nodemon dist/server.js",
"dev": "npm-run-all --parallel watch nodemon",
"start": "ts-node src/server.ts",
"client": "cd ../ && npm run dev --prefix client",
"runall": "npm-run-all --parallel client dev",
"typeorm": "node --require ts-node/register ./node_modules/typeorm/cli.js",
"migration:up": "typeorm migration:run",
"migration:down": "typeorm migration:revert",
"migration:generate": "typeorm migration:generate -n 'orm_migrations'"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"apollo-server-express": "^2.16.1",
"argon2": "^0.26.2",
"connect-redis": "^5.0.0",
"cors": "^2.8.5",
"dataloader": "^2.0.0",
"dotenv-safe": "^8.2.0",
"express": "^4.17.1",
"express-async-errors": "^3.1.1",
"express-session": "^1.17.1",
"graphql": "^15.3.0",
"ioredis": "^4.17.3",
"module-alias": "^2.2.2",
"path": "^0.12.7",
"pgtools": "^0.3.0",
"reflect-metadata": "^0.1.13",
"type-graphql": "^1.0.0-rc.3",
"typeorm": "^0.2.25",
"uuid": "^8.3.0",
"winston": "^3.3.3"
},
"devDependencies": {
"@types/connect-redis": "0.0.14",
"@types/cors": "^2.8.8",
"@types/express": "^4.17.8",
"@types/express-session": "^1.17.0",
"@types/graphql": "^14.5.0",
"@types/ioredis": "^4.17.7",
"@types/node": "^8.10.66",
"@types/nodemailer": "^6.4.0",
"@types/pg": "^7.14.6",
"@types/uuid": "^8.3.0",
"gen-env-types": "^1.0.4",
"nodemon": "^2.0.6",
"npm-run-all": "^4.1.5",
"pg": "^8.4.2",
"ts-node": "^8.10.2",
"typescript": "^3.9.7"
},
"_moduleAliases": {
"@": "dist/"
}
}
注意!
当我尝试从 apolloServer 配置中删除 uploads: false
时,我收到另一个错误:
"Variable "$file" got invalid value {}; Upload value invalid."
确实在我看到的表单数据中
------WebKitFormBoundarybNufV7QLX3EU1SN6 Content-Disposition: form-data; name="operations"
{"operationName":"uploadImage","variables":{"file":null},"query":"mutationuploadImage($file: Upload!) {\n uploadImage(file: $file)\n}\n"}------WebKitFormBoundarybNufV7QLX3EU1SN6 Content-Disposition: form-data; name="map"
{"1":["variables.file"]}------WebKitFormBoundarybNufV7QLX3EU1SN6 Content-Disposition: form-data; name="1"; filename="Screen Shot 2020-11-20 at 17.56.14.png"Content-Type: image/png
------WebKitFormBoundarybNufV7QLX3EU1SN6--
我 100% 确定我通过了文件。
最佳答案
我在我的 NextJs 项目中遇到了同样的问题,我发现 Upload 的解析器检查值是否为 instanceOf Upload,这在某种程度上不起作用。
我通过创建自己的解析器来修复它,而不是像这样使用“graphql-upload”包:
解决方案 1:
export const resolvers: Resolvers = {
Upload: new GraphQLScalarType({
name: 'Upload',
description: 'The `Upload` scalar type represents a file upload.',
parseValue(value) {
return value;
},
parseLiteral(ast) {
throw new GraphQLError('Upload literal unsupported.', ast);
},
serialize() {
throw new GraphQLError('Upload serialization unsupported.');
},
})
};
解决方案 2:
或者您可以不为此类型声明任何解析器。
注意:请确保您在架构中声明了标量类型的上传,并且您需要将上传字段添加到您的 Apollo 服务器配置中:
const apolloServer = new ApolloServer({
uploads: {
maxFileSize: 10000000, // 10 MB
maxFiles: 20
},
.
.
.
关于express - 无法在 Next.js 应用程序 : POST body missing 中使用 Apollo-client GraphQL 上传文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64971480/
我在网上搜索但没有找到任何合适的文章解释如何使用 javascript 使用 WCF 服务,尤其是 WebScriptEndpoint。 任何人都可以对此给出任何指导吗? 谢谢 最佳答案 这是一篇关于
我正在编写一个将运行 Linux 命令的 C 程序,例如: cat/etc/passwd | grep 列表 |剪切-c 1-5 我没有任何结果 *这里 parent 等待第一个 child (chi
所以我正在尝试处理文件上传,然后将该文件作为二进制文件存储到数据库中。在我存储它之后,我尝试在给定的 URL 上提供文件。我似乎找不到适合这里的方法。我需要使用数据库,因为我使用 Google 应用引
我正在尝试制作一个宏,将下面的公式添加到单元格中,然后将其拖到整个列中并在 H 列中复制相同的公式 我想在 F 和 H 列中输入公式的数据 Range("F1").formula = "=IF(ISE
问题类似于this one ,但我想使用 OperatorPrecedenceParser 解析带有函数应用程序的表达式在 FParsec . 这是我的 AST: type Expression =
我想通过使用 sequelize 和 node.js 将这个查询更改为代码取决于在哪里 select COUNT(gender) as genderCount from customers where
我正在使用GNU bash,版本5.0.3(1)-发行版(x86_64-pc-linux-gnu),我想知道为什么简单的赋值语句会出现语法错误: #/bin/bash var1=/tmp
这里,为什么我的代码在 IE 中不起作用。我的代码适用于所有浏览器。没有问题。但是当我在 IE 上运行我的项目时,它发现错误。 而且我的 jquery 类和 insertadjacentHTMl 也不
我正在尝试更改标签的innerHTML。我无权访问该表单,因此无法编辑 HTML。标签具有的唯一标识符是“for”属性。 这是输入和标签的结构:
我有一个页面,我可以在其中返回用户帖子,可以使用一些 jquery 代码对这些帖子进行即时评论,在发布新评论后,我在帖子下插入新评论以及删除 按钮。问题是 Delete 按钮在新插入的元素上不起作用,
我有一个大约有 20 列的“管道分隔”文件。我只想使用 sha1sum 散列第一列,它是一个数字,如帐号,并按原样返回其余列。 使用 awk 或 sed 执行此操作的最佳方法是什么? Accounti
我需要将以下内容插入到我的表中...我的用户表有五列 id、用户名、密码、名称、条目。 (我还没有提交任何东西到条目中,我稍后会使用 php 来做)但由于某种原因我不断收到这个错误:#1054 - U
所以我试图有一个输入字段,我可以在其中输入任何字符,但然后将输入的值小写,删除任何非字母数字字符,留下“。”而不是空格。 例如,如果我输入: 地球的 70% 是水,-!*#$^^ & 30% 土地 输
我正在尝试做一些我认为非常简单的事情,但出于某种原因我没有得到想要的结果?我是 javascript 的新手,但对 java 有经验,所以我相信我没有使用某种正确的规则。 这是一个获取输入值、检查选择
我想使用 angularjs 从 mysql 数据库加载数据。 这就是应用程序的工作原理;用户登录,他们的用户名存储在 cookie 中。该用户名显示在主页上 我想获取这个值并通过 angularjs
我正在使用 autoLayout,我想在 UITableViewCell 上放置一个 UIlabel,它应该始终位于单元格的右侧和右侧的中心。 这就是我想要实现的目标 所以在这里你可以看到我正在谈论的
我需要与 MySql 等效的 elasticsearch 查询。我的 sql 查询: SELECT DISTINCT t.product_id AS id FROM tbl_sup_price t
我正在实现代码以使用 JSON。 func setup() { if let flickrURL = NSURL(string: "https://api.flickr.com/
我尝试使用for循环声明变量,然后测试cols和rols是否相同。如果是,它将运行递归函数。但是,我在 javascript 中执行 do 时遇到问题。有人可以帮忙吗? 现在,在比较 col.1 和
我举了一个我正在处理的问题的简短示例。 HTML代码: 1 2 3 CSS 代码: .BB a:hover{ color: #000; } .BB > li:after {
我是一名优秀的程序员,十分优秀!