ファイルのアップロードは突然変異のようです。それはしばしば他のデータを伴います。しかし、それは大きなバイナリブロブなので、GraphQLがどのようにそれに対処できるかはわかりません。あなたはRelayで構築されたアプリにファイルアップロードをどのように統合しますか?React-Relayアプリでファイルアップロードをどのように行いますか?
答えて
見つけたan explanation in the docs。 Relay.Mutationをサブクラス化し、getFiles関数を実装できます。
また、express-graphqlはサーバ側でこれを処理する方法のテストケースにan exampleを提供します。
まず、フロントエンドコンポーネントにリレー更新を書き込む必要があります。
onDrop: function(files) {
files.forEach((file)=> {
Relay.Store.commitUpdate(
new AddImageMutation({
file,
images: this.props.User,
}),
{onSuccess, onFailure}
);
});
},
そして、フロントエンドに変異を実装することにより、次のとおりです:このように
class AddImageMutation extends Relay.Mutation {
static fragments = {
images:() => Relay.QL`
fragment on User {
id,
}`,
};
getMutation() {
return Relay.QL`mutation{ introduceImage }`;
}
getFiles() {
return {
file: this.props.file,
};
}
getVariables() {
return {
imageName: this.props.file.name,
};
}
getFatQuery() {
return Relay.QL`
fragment on IntroduceImagePayload {
User {
images(first: 30) {
edges {
node {
id,
}
}
}
},
newImageEdge,
}
`;
}
getConfigs() {
return [{
type: 'RANGE_ADD',
parentName: 'User',
parentID: this.props.images.id,
connectionName: 'images',
edgeName: 'newImageEdge',
rangeBehaviors: {
'': 'prepend',
},
}];
}
}
そして最後には、サーバー/スキーマのハンドラを実装します。
const imageMutation = Relay.mutationWithClientMutationId({
name: 'IntroduceImage',
inputFields: {
imageName: {
type: new GraphQL.GraphQLNonNull(GraphQL.GraphQLString),
},
},
outputFields: {
newImageEdge: {
type: ImageEdge,
resolve: (payload, args, options) => {
const file = options.rootValue.request.file;
//write the image to you disk
return uploadFile(file.buffer, filePath, filename)
.then(() => {
/* Find the offset for new edge*/
return Promise.all(
[(new myImages()).getAll(),
(new myImages()).getById(payload.insertId)])
.spread((allImages, newImage) => {
const newImageStr = JSON.stringify(newImage);
/* If edge is in list return index */
const offset = allImages.reduce((pre, ele, idx) => {
if (JSON.stringify(ele) === newImageStr) {
return idx;
}
return pre;
}, -1);
return {
cursor: offset !== -1 ? Relay.offsetToCursor(offset) : null,
node: newImage,
};
});
});
},
},
User: {
type: UserType,
resolve:() => (new myImages()).getAll(),
},
},
mutateAndGetPayload: (input) => {
//break the names to array.
let imageName = input.imageName.substring(0, input.imageName.lastIndexOf('.'));
const mimeType = input.imageName.substring(input.imageName.lastIndexOf('.'));
//wirte the image to database
return (new myImages())
.add(imageName)
.then(id => {
//prepare to wirte disk
return {
insertId: id,
imgNmae: imageName,
};
});
},
});
あなたは私のレポhttps://github.com/bfwg/relay-gallery でそれらを見つけることができます上のすべてのコードのライブデモhttp://fanjin.computer
あなたの答えに関連するコードを含めてください。スタックオーバーフローは、リンクの腐敗を防ぐために、答えの "コア"の外側のリンクに頼っています。関連するものだけを引用し、完全なリポジトリにリンクすることは完全にOKです。 – mech
私は自分の答えを更新しました。 –
もあり、私は単にである、彼のblogからマルク・アンドレ・ジルーの調査結果を共有していますRails-具体的なので、私はより一般的なものにしようとし、@ニックによって提供された答えの詳細を提供します。
- クライアント側のJavaScriptコード
- サーバー側のサーバー固有のコード
クライアント側のJavaScriptコード
クライアント - :
は、2つの部分がありますサイドコードはさらに2つの部分で構成されています:
Relay.Mutation(UploadFileMutation)を拡張ファイルをアップロードする突然変異
// The actual mutation class UploadFileMutation extends Relay.Mutation { getFiles() { return { file: this.props.file, }; } // ... Rest of your mutation }
ファイルを選択するためのUIをレンダリングするように反応成分(FileUploader)が含まれ、そして突然変異を呼び出すコンポーネントアップロードに
// A react component to upload a file class FileUploader extends React.Component { onSubmit() { const name = this.refs.name.value; const file = this.refs.fileInput.files.item(0); Relay.Store.update( new UploadFileMutation({ name: name, file: file, }) ); } // ... Rest of React component, e.g., render() }
サーバー側のサーバー固有のコードを実行する
サーバ側コードはまた、2つの部分からなる:
- 部分は、MIMEマルチパート形式でアップロードされたファイルを検索する処理とGraphQLスキーマで定義された突然変異にそれを渡します。 NodeJSとRailsの例を提供します。これは他のサーバのためのソリューションを導き出すのに役立ちます。 NodeJS Expressサーバについて
(express-graqphlテストケースから抽出@Nickによって指摘されるように):
import multer from 'multer';
var app = express();
var graphqlHTTP = require('express-graphql');
// Multer provides multipart form data parsing.
var storage = multer.memoryStorage();
app.use(urlString(), multer({ storage }).single('file'));
// Providing the request, which contains the file MIME
// multipart as `rootValue` to enable it to
// be accessible from within Schema resolve functions.
app.use(urlString(), graphqlHTTP(req => {
return {
schema: YourMutationSchema,
rootValue: { request: req }
};
}));
同様に、非JSサーバに対して、例えば、RubyOnRails:
def create
query_string = params[:query]
query_variables = ensure_hash(params[:variables]) || {}
query = GraphQL::Query.new(
YourSchema,
query_string,
variables: query_variables,
# Shove the file MIME multipart into context to make it
# accessible by GraphQL Schema Mutation resolve methods
context: { file: request.params[:file] }
)
- Mutationは、渡されたMIMEマルチパートを取得できます。
:RailsのGraphQLスキーマの
var YourMutationSchema = new GraphQLSchema({
query: new GraphQLObjectType({
// ... QueryType Schema
}),
mutation: new GraphQLObjectType({
name: 'MutationRoot',
fields: {
uploadFile: {
type: UploadedFileType,
resolve(rootValue) {
// Access file MIME multipart using
const _file = rootValue.request.file;
// ... Do something with file
}
}
}
})
});
:
AddFileMutation = GraphQL::Relay::Mutation.define do
name "AddFile"
input_field :name, !types.String
# ... Add your standard mutation schema stuff here
resolve -> (args, ctx) {
# Retrieve the file MIME multipart
file = ctx[:file]
raise StandardError.new("Expected a file") unless file
# ... Do something with file
}
end
すばらしい答え! :) – bryce
リレー現代で、他の回答に追加するには、あなたからファイルを送信する方法に小さな変更がありましたクライアント。コンポーネントの
UploadFileMutation.js
// @flow
import { commitMutation, graphql } from 'react-relay';
import type { Environment } from 'react-relay';
import type { UploadFileInput, UploadFileMutationResponse } from './__generated__/uploadFileMutation.graphql';
const mutation = graphql`
mutation UploadFileMutation($input: UploadFileInput!) {
UploadFile(input: $input) {
error
file {
url
}
}
}
`;
const getOptimisticResponse = (file: File | Blob) => ({
UploadFile: {
error: null,
file: {
url: file.uri,
},
},
});
function commit(
environment: Environment,
{ fileName }: UploadFileInput,
onCompleted: (data: UploadFileMutationResponse) => void,
onError:() => void,
uploadables,
) {
return commitMutation(environment, {
mutation,
variables: {
input: { fileName },
},
optimisticResponse: getOptimisticResponse(uploadables.fileToUpload),
onCompleted,
onError,
uploadables,
});
}
export default { commit };
使用法:
代わりにあなたの突然変異でgetFiles
を有し、コンストラクタにファイルを渡すのは、次のようなものを使用することができます
const uploadables = {
fileToUpload: file, // file is the value of an input field for example
};
UploadFileMutation.commit(
this.props.relay.environment,
{ fileName },
onCompleted,
onError,
uploadables
);
uploadables
設定オプションは隠されていますが、ドキュメントには言及されていませんが、ここにあります:https://github.com/facebook/relay/blob/c4430643002ec409d815366b0721ba88ed3a855a/packages/relay-runtime/mutations/commitRelayModernMutation.js#L32
- 1. ファイルアップロードのファイルタイプを検証するにはどうすればよいですか?
- 2. どのようにプロダクションモードでreact-nativeアプリを実行しますか?
- 3. GAEアプリはapp.yamlなしでどのように実行できますか?
- 4. iOS NSUserDefaults。アプリのバックグラウンド/フォアグラウンドでどのように行動しますか?
- 5. どのように私のアプリをスピードアップできますか?
- 6. 世界銀行のアプリはどのようにこのようなポップアップを実現していますか?
- 7. DeformとColanderを使用してファイルアップロードを行うにはどうすればいいですか?
- 8. iOS - Clearアプリのようなビジュアルエフェクトを実行するにはどうすればよいですか?
- 9. dropbox.comの複数のファイルアップロード機能はどのように機能しますか?
- 10. ColdFusion 9のMulitファイルアップロードはどのように機能しますか?
- 11. 大容量ファイルのHTTPファイルアップロードはどのように機能しますか?
- 12. Railsでこれをどのように行いますか?
- 13. 同じようなカードを見せないように、どのようにタイダーのようなアプリですか?
- 14. ngファイルアップロードでJavaScriptファイルをアップロードできないようにする
- 15. アプリの実行中にバックグラウンドでサービスコールを行うにはどうすればいいですか
- 16. iOS 10より前のUNNotificationServiceExtensionでアプリを実行するにはどうすればよいですか?
- 17. ElectronアプリからのファイルアップロードのマルチパートPOSTリクエスト
- 18. タブレットでのアプリの実行を無効にするにはどうすればよいですか?
- 19. iOSアプリ内で「このアプリの使い方」チュートリアルをどのように構築できますか?
- 20. Angular5 + MD2アプリのレイアウトをどのように書きますか?
- 21. Facebookのアプリをどのようにデバッグしますか?
- 22. どのように3Dオブジェクトの定義を実行時にアプリに渡すか?
- 23. MemoryCacheはいつ/どのようにハウスキーピングを行いますか?
- 24. Emberアプリのキュウリスタイルの受け入れテストを行うにはどうすればよいですか?
- 25. G-Suiteマーケットプレイスのアプリはどのようなアプリですか?
- 26. ajaxファイルアップロードで追加のパラメータを送信するにはどうすればよいですか?
- 27. Sails JSでオプションのファイルアップロードを処理するにはどうすればよいですか?
- 28. 複数のファイルアップロード名をデータベースに保存するにはどうすればよいですか?
- 29. このアプリはGMailにどのようにアクセスしますか?
- 30. Compojure/Luminusアプリでどのようにリダイレクト301 httpを行うことができますか?
あなたはそれをうまく動作させましたか?共有することはできますか? –
しました。私はチャンスを得たときにこれをもっと詳細に更新します。 –