2015-10-10 7 views
15

एक फ़ाइल अपलोड एक उत्परिवर्तन की तरह लगता है। यह अक्सर अन्य डेटा के साथ होता है। लेकिन यह एक बड़ा बाइनरी ब्लॉब है, इसलिए मुझे यकीन नहीं है कि ग्राफक्यूएल इसके साथ कैसे निपट सकता है। रिले के साथ बनाए गए ऐप में फ़ाइल अपलोड को आप कैसे एकीकृत करेंगे?आप एक रिएक्ट-रिले ऐप में फ़ाइल अपलोड कैसे करेंगे?

उत्तर

5

मुझे an explanation in the docs मिला। आप Relay.Mutation subclass कर सकते हैं और getFiles फ़ंक्शन को कार्यान्वित कर सकते हैं।

इसके अलावा, एक्सप्रेस-ग्राफक्ल सर्वर के पक्ष में इसे संभालने के तरीके के परीक्षण मामलों में an example प्रदान करता है।

+0

क्या आप इसे काम करने में कामयाब रहे? क्या आप साझा कर सकते हैं? –

+0

मैंने किया। जब मुझे मौका मिलता है तो मैं इसे अधिक जानकारी के साथ अपडेट कर दूंगा। –

10

सबसे पहले आपको अपने फ्रंटएंड घटक में रिले अपडेट लिखना होगा। इस तरह:

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, 
     }; 
    }); 
    }, 
}); 

सभी Rails- कोड ऊपर आप उन्हें अपने रेपो में पा सकते हैं https://github.com/bfwg/relay-gallery वहाँ भी है एक लाइव डेमो http://fanjin.computer

+0

कृपया अपने उत्तर में प्रासंगिक कोड शामिल करें। लिंक रोट को रोकने के लिए, उत्तर के "कोर" के लिए बाहरी लिंक पर निर्भर स्टैक ओवरफ़्लो को हतोत्साहित करता है। केवल प्रासंगिकता को उद्धृत करना ठीक है, और फिर पूर्ण भंडार से लिंक करें। – mech

+1

समझ गया! मैंने अपना जवाब अपडेट किया। –

4

मैं केवल अपने blog से मार्क-आंद्रे गिरौक्स के निष्कर्षों साझा कर रहा हूँ, जो विशिष्ट, इसलिए मैं इसे अधिक सामान्य बनाने और @ निक द्वारा प्रदान किए गए उत्तर का विवरण प्रदान करने की कोशिश करूंगा।

  • क्लाइंट-साइड जावास्क्रिप्ट कोड
  • सर्वर साइड सर्वर विशेष कोड

क्लाइंट-साइड जावास्क्रिप्ट कोड

ग्राहक:

2 भागों रहे हैं साइड कोड में 2 भाग होते हैं:

  1. फ़ाइल अपलोड करने के उत्परिवर्तन, जो Relay.Mutation (UploadFileMutation)

    // The actual mutation 
    class UploadFileMutation extends Relay.Mutation { 
        getFiles() { 
        return { 
         file: this.props.file, 
        }; 
        } 
    
        // ... Rest of your mutation 
    } 
    
  2. घटक है कि फ़ाइल का चयन के लिए यूआई रेंडर करने के लिए प्रतिक्रिया घटक (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 हिस्से होते हैं:

  1. हिस्सा MIME बहुखण्डीय प्रारूप में अपलोड की गई फ़ाइल को पुन: प्राप्त संभालने के लिए और यह उत्परिवर्तन GraphQL स्कीमा में निर्धारित करने के लिए पारित करने के लिए। हम नोडजेएस और रेल उदाहरण प्रदान करते हैं, जो आपको अन्य सर्वरों के लिए समाधान प्राप्त करने में मदद कर सकते हैं।

NodeJS एक्सप्रेस सर्वर के लिए (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 } 
     }; 
    })); 

इसी तरह, एक गैर जे एस सर्वर के लिए, उदाहरण के लिए, 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] } 
    ) 
  1. उत्परिवर्तन फ़ाइल MIME मल्टीपार्ट को
01 को पुनर्प्राप्त कर सकता है

जावास्क्रिप्ट 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 
      } 
      } 
     } 
     }) 
    }); 

रेल के लिए GraphQL स्कीमा:

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 
+0

महान जवाब! :) – bryce

1

रिले आधुनिक के साथ अन्य उत्तर देने के लिए जोड़ने के लिए, वहाँ कैसे आप से फाइल भेजना चाहिए पर एक छोटा सा परिवर्तन किया गया ग्राहक।

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

संबंधित मुद्दे