Dosya yüklemesi mutasyona benziyor. Çoğu zaman diğer veriler eşlik ediyor. Ama büyük bir ikili blob, bu yüzden GraphQL'in bununla nasıl başedebileceğinden emin değilim. Dosya yüklemelerini Relay ile oluşturulmuş bir uygulamaya nasıl entegre edersiniz?Bir React-Relay uygulamasında dosya yüklemelerini nasıl yaparsınız?
cevap
an explanation in the docs. Relay.Mutation alt sınıfını ve getFiles işlevini uygulayabilirsiniz.
Ayrıca, express-graphql, sunucu tarafında bunun nasıl işleneceği konusunda testlerinde an example sağlar.
Öncelikle ön uç bileşeninize Röle güncellemesini yazmanız gerekir. Bunun gibi :
onDrop: function(files) {
files.forEach((file)=> {
Relay.Store.commitUpdate(
new AddImageMutation({
file,
images: this.props.User,
}),
{onSuccess, onFailure}
);
});
},
Sonra önyüz üzerinde mutasyon uygulayarak izleyin:
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',
},
}];
}
}
Ve son sunucu/şema üzerinde işleyicisi uygulamak.
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,
};
});
},
});
Rails- da bir canlı tanıtım
http://fanjin.computer
Lütfen cevabınıza ilgili kodu ekleyin. Yığın taşmasını önlemek için Yığın Taşması, bir cevabın "çekirdeği" için dış bağlantılara güvenmekten vazgeçirir. Sadece neyin uygun olduğunu alıntılamak ve ardından tam depoya bağlantı vermek tamamen uygun. – mech
Anladım! Cevabımı güncelledim. –
Ben sadece onun blog Marc-Andre Giroux'nun bulgularını paylaşıyorum yoktur https://github.com/bfwg/relay-gallery sen benim repo bunları bulabilirsiniz Yukarıdaki kod, All hangi Spesifik, bu yüzden daha jenerik yapmak ve @Nick tarafından sağlanan cevabın ayrıntılarını sağlamaya çalışacağım.
- İstemci tarafı JavaScript kodu
- Sunucu tarafı sunucu özgü kod
İstemci tarafı JavaScript kodu
client-:
2 bölümü vardır yan kod ayrıca 2 bölümden oluşur:
Relay.Mutation (UploadFileMutation)
// The actual mutation class UploadFileMutation extends Relay.Mutation { getFiles() { return { file: this.props.file, }; } // ... Rest of your mutation }
dosyayı seçmek için UI işlemek ve Tepkisiz bileşeni (FileUploader) içeren bileşen uzanır ve mutasyon çağıran dosya yüklemek için mutasyon, yükle
// 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() }
Sunucu tarafı Sunucu Özgü Kod yapmak
sunucu tarafında kodu da 2 kısımdan oluşur:
- parçalı MIME çok parçalı biçimde yüklenmiş dosya alma kolu ve GraphQL şemada tanımlanan mutasyon için geçmek için. Diğer sunucular için çözümler üretmenize yardımcı olan NodeJS ve Rails örneklerini sunuyoruz. NodeJS Hızlı sunucusu için
(express-graqphl test durumlarda elde @ Nick tarafından işaret edildiği gibi):
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 }
};
}));
Benzer bir şekilde, JS olmayan sunucusunun, örneğin, 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] }
)
- Mutasyon, iletilen MIME multipart dosyasını geri alabilir
:
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
}
}
}
})
});
Raylar için GraphQL Şeması:
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
harika cevap! :) – bryce
Röle Modern ile, diğer cevaplara eklemek için dosyaları göndermesi gerektiğini nasıl küçük bir değişiklik oldu müşteri.
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 };
: Bunun yerine mutasyon birKullanım bileşeni üzerinde
getFiles
sahip ve yapıcı dosyaları geçme, aşağıdaki gibi bir şey kullanabilirsiniz
const uploadables = {
fileToUpload: file, // file is the value of an input field for example
};
UploadFileMutation.commit(
this.props.relay.environment,
{ fileName },
onCompleted,
onError,
uploadables
);
The uploadables
config seçeneği gizlidir, çünkü dokümanlar üzerinde hiç bir şey yoktur, ancak şu adreste bulunabilir: https://github.com/facebook/relay/blob/c4430643002ec409d815366b0721ba88ed3a855a/packages/relay-runtime/mutations/commitRelayModernMutation.js#L32
Çalışmayı başardı mı? paylaşabilir misin? –
Yaptım. Bir şans elde ettiğimde bunu daha fazla ayrıntıyla güncelleyeceğim. –