{"id":34819,"date":"2025-11-22T11:40:37","date_gmt":"2025-11-22T08:40:37","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=34819"},"modified":"2025-11-22T11:40:37","modified_gmt":"2025-11-22T08:40:37","slug":"graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/","title":{"rendered":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?"},"content":{"rendered":"<p><body><\/p>\n<h2>GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?<\/h2>\n<h3>Giri\u015f<\/h3>\n<p>G\u00fcn\u00fcm\u00fcz web uygulamalar\u0131n\u0131n ayr\u0131lmaz bir par\u00e7as\u0131 olan dosya y\u00f6netimi, kullan\u0131c\u0131lar\u0131n belge, g\u00f6rsel, video gibi \u00e7e\u015fitli medya t\u00fcrlerini y\u00fcklemesine, indirmesine, g\u00f6r\u00fcnt\u00fclemesine ve silmesine olanak tan\u0131r. Bu t\u00fcr i\u015flevsellikleri sa\u011flamak i\u00e7in g\u00fc\u00e7l\u00fc ve esnek bir mimariye ihtiya\u00e7 duyar\u0131z. Geleneksel REST API&#8217;leri bu konuda iyi bir i\u015f \u00e7\u0131karsa da, GraphQL&#8217;in sundu\u011fu esneklik ve veri \u00e7ekme g\u00fcc\u00fc, \u00f6zellikle karma\u015f\u0131k veri yap\u0131lar\u0131 ve kaynaklar aras\u0131 ili\u015fkilerin oldu\u011fu senaryolarda \u00f6nemli avantajlar sa\u011flayabilir. Bu makalede, modern bir dosya i\u015fleme uygulamas\u0131n\u0131 GraphQL&#8217;i bir arka u\u00e7 teknolojisi olarak kullanarak ve Vue.js&#8217;i \u00f6n y\u00fcz \u00e7er\u00e7evesi olarak tercih ederek nas\u0131l geli\u015ftirece\u011fimizi ayr\u0131nt\u0131l\u0131 bir \u015fekilde inceleyece\u011fiz. Ad\u0131m ad\u0131m bir geli\u015ftirme s\u00fcreciyle, hem arka u\u00e7ta hem de \u00f6n y\u00fczde dosya y\u00fckleme, listeleme ve silme gibi temel i\u015flevleri nas\u0131l uygulayaca\u011f\u0131m\u0131z\u0131 \u00f6\u011frenece\u011fiz.<\/p>\n<h3>Dosya \u0130\u015flemede Neden GraphQL Tercih Edilmeli?<\/h3>\n<p>GraphQL, API&#8217;ler i\u00e7in bir sorgu dili ve \u00e7al\u0131\u015fma zaman\u0131 olup, istemcilerin tam olarak ihtiya\u00e7 duyduklar\u0131 veriyi istemesine olanak tan\u0131r. Bu, \u00f6zellikle dosya i\u015fleme gibi, dosyan\u0131n kendisiyle birlikte metadata (dosya ad\u0131, boyutu, t\u00fcr\u00fc, y\u00fcklenme tarihi vb.) y\u00f6netilmesi gereken durumlarda b\u00fcy\u00fck faydalar sa\u011flar.<\/p>\n<h4>REST ve GraphQL Kar\u015f\u0131la\u015ft\u0131rmas\u0131<\/h4>\n<p>Geleneksel REST API&#8217;lerinde, dosya y\u00fckleme genellikle ayr\u0131 bir endpoint (\u00f6rn. <code>\/upload<\/code>) \u00fczerinden bir <code>multipart\/form-data<\/code> iste\u011fi ile yap\u0131l\u0131r. Dosya metadata&#8217;s\u0131 ayr\u0131 bir istek veya ayn\u0131 iste\u011fin bir par\u00e7as\u0131 olarak g\u00f6nderilebilir. Dosyalar\u0131 listelemek i\u00e7in ba\u015fka bir endpoint (\u00f6rn. <code>\/files<\/code>) kullan\u0131l\u0131r ve genellikle t\u00fcm metadata seti geri d\u00f6ner.<\/p>\n<p>GraphQL ise, dosya y\u00fcklemeyi &#8220;GraphQL Multipart Request Specification&#8221; ad\u0131 verilen \u00f6zel bir y\u00f6ntemle ele al\u0131r. Bu y\u00f6ntem, bir GraphQL mutasyonunun bir par\u00e7as\u0131 olarak dosya verilerini g\u00f6ndermeyi m\u00fcmk\u00fcn k\u0131lar. Bu sayede, dosya y\u00fckleme i\u015flemi s\u0131ras\u0131nda dosya metadata&#8217;s\u0131n\u0131 ve hatta di\u011fer ilgili verileri (\u00f6rne\u011fin, dosyan\u0131n hangi kullan\u0131c\u0131ya ait oldu\u011fu, hangi projeye y\u00fcklendi\u011fi) tek bir istekte g\u00f6nderebiliriz. Benzer \u015fekilde, dosyalar\u0131 listelerken, istemci yaln\u0131zca ihtiya\u00e7 duydu\u011fu metadata alanlar\u0131n\u0131 sorgulayabilir, bu da a\u011f trafi\u011fini azalt\u0131r ve performans\u0131 art\u0131r\u0131r.<\/p>\n<h4>GraphQL&#8217;in Avantajlar\u0131<\/h4>\n<p>*   <strong>Tek \u0130stekle \u00c7oklu \u0130\u015flem:<\/strong> Dosya y\u00fcklerken metadata ile birlikte di\u011fer ilgili verileri tek bir mutasyon i\u00e7inde g\u00f6nderebilme.<br \/>\n*   <strong>Veri A\u015f\u0131r\u0131 Getirme\/Az Getirme Sorunlar\u0131n\u0131n \u00d6nlenmesi:<\/strong> \u0130stemci sadece ihtiya\u00e7 duydu\u011fu dosya metadata alanlar\u0131n\u0131 sorgular. Bu, \u00f6zellikle \u00e7ok say\u0131da dosya listelenirken bant geni\u015fli\u011finden tasarruf sa\u011flar.<br \/>\n*   <strong>G\u00fc\u00e7l\u00fc Tip Sistemi:<\/strong> GraphQL&#8217;in tip sistemi, dosya y\u00fckleme ve metadata y\u00f6netimi i\u00e7in net ve g\u00fcvenli bir API tan\u0131m\u0131 sunar. Bu, geli\u015ftirme s\u00fcrecini kolayla\u015ft\u0131r\u0131r ve hatalar\u0131 azalt\u0131r.<br \/>\n*   <strong>Geli\u015ftirici Deneyimi:<\/strong> GraphQL ara\u00e7lar\u0131 (\u00f6rne\u011fin, GraphiQL, Apollo Studio) API&#8217;yi ke\u015ffetmeyi ve test etmeyi kolayla\u015ft\u0131r\u0131r.<\/p>\n<h3>Temel Teknolojiler<\/h3>\n<p>Bu uygulamay\u0131 geli\u015ftirmek i\u00e7in a\u015fa\u011f\u0131daki temel teknolojileri kullanaca\u011f\u0131z:<\/p>\n<h4>GraphQL<\/h4>\n<p>Arka u\u00e7ta API katman\u0131n\u0131 olu\u015fturmak i\u00e7in GraphQL kullanaca\u011f\u0131z. Genellikle Node.js ekosisteminde Apollo Server veya NestJS gibi \u00e7er\u00e7eveler tercih edilir. Bu makalede, Apollo Server&#8217;\u0131 Node.js ve Express ile birlikte kullanaca\u011f\u0131z.<\/p>\n<h4>Vue.js<\/h4>\n<p>\u00d6n y\u00fcz kullan\u0131c\u0131 aray\u00fcz\u00fcn\u00fc olu\u015fturmak i\u00e7in progresif JavaScript \u00e7er\u00e7evesi Vue.js&#8217;i kullanaca\u011f\u0131z. Vue&#8217;nun reaktif veri ba\u011flama ve bile\u015fen tabanl\u0131 yap\u0131s\u0131, dosya listeleme ve y\u00fckleme aray\u00fczlerini geli\u015ftirmeyi kolayla\u015ft\u0131r\u0131r.<\/p>\n<h4>Arka U\u00e7 \u00c7er\u00e7evesi ve K\u00fct\u00fcphaneler<\/h4>\n<p>*   <strong>Node.js &#038; Express:<\/strong> Arka u\u00e7 sunucusunu kurmak i\u00e7in.<br \/>\n*   <strong>Apollo Server:<\/strong> GraphQL sunucusunu uygulamak i\u00e7in.<br \/>\n*   <strong><code>graphql-upload<\/code>:<\/strong> GraphQL ile dosya y\u00fcklemeyi desteklemek i\u00e7in standart bir \u00e7\u00f6z\u00fcm.<br \/>\n*   <strong><code>multer<\/code> (iste\u011fe ba\u011fl\u0131, alternatif olarak <code>fs<\/code> mod\u00fcl\u00fc):<\/strong> Dosyalar\u0131 sunucu taraf\u0131nda depolamak i\u00e7in.<br \/>\n*   <strong>Veritaban\u0131 (MongoDB\/PostgreSQL):<\/strong> Dosyalar\u0131n metadata&#8217;s\u0131n\u0131 (ad\u0131, boyutu, t\u00fcr\u00fc, depolama yolu vb.) saklamak i\u00e7in. Bu makalede basitlik ad\u0131na yerel dosya sistemini ve bir veritaban\u0131 olmadan ilerleyebiliriz, ancak ger\u00e7ek d\u00fcnya uygulamalar\u0131nda veritaban\u0131 kullan\u0131m\u0131 kritik \u00f6neme sahiptir.<\/p>\n<h4>\u00d6n Y\u00fcz K\u00fct\u00fcphaneleri<\/h4>\n<p>*   <strong>Vue CLI:<\/strong> Vue projesini h\u0131zl\u0131ca ba\u015flatmak i\u00e7in.<br \/>\n*   <strong>Apollo Client:<\/strong> Vue uygulamas\u0131ndan GraphQL API&#8217;sine istekler g\u00f6ndermek i\u00e7in.<br \/>\n*   <strong><code>apollo-upload-client<\/code>:<\/strong> Apollo Client ile dosya y\u00fcklemeyi desteklemek i\u00e7in \u00f6zel bir ba\u011flant\u0131 (link).<\/p>\n<h3>Arka U\u00e7 Uygulamas\u0131 (Node.js, Express, Apollo Server)<\/h3>\n<h4>Proje Kurulumu<\/h4>\n<p>\u0130lk olarak, yeni bir Node.js projesi olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-bash\">mkdir graphql-file-upload-backend\ncd graphql-file-upload-backend\nnpm init -y\nnpm install express apollo-server graphql graphql-upload\nnpm install --save-dev nodemon<\/code><\/pre>\n<p><code>package.json<\/code> dosyan\u0131za <code>start<\/code> ve <code>dev<\/code> script&#8217;lerini ekleyin:<\/p>\n<pre><code class=\"language-json\">\"scripts\": {\n  \"start\": \"node src\/index.js\",\n  \"dev\": \"nodemon src\/index.js\"\n}<\/code><\/pre>\n<h4>GraphQL \u015eema Tan\u0131m\u0131<\/h4>\n<p>Dosya y\u00fckleme, listeleme ve silme i\u00e7in GraphQL \u015femas\u0131n\u0131 tan\u0131mlayal\u0131m. <code>Upload<\/code> scalar tipi <code>graphql-upload<\/code> k\u00fct\u00fcphanesi taraf\u0131ndan sa\u011flan\u0131r ve dosya verilerini temsil eder.<\/p>\n<p><code>src\/schema.js<\/code>:<\/p>\n<pre><code class=\"language-javascript\">const { gql } = require('apollo-server-express');\n\nconst typeDefs = gql<code>\n  scalar Upload\n\n  type File {\n    id: ID!\n    filename: String!\n    mimetype: String!\n    encoding: String!\n    url: String!\n    size: Float\n  }\n\n  type Query {\n    hello: String\n    files: [File!]!\n  }\n\n  type Mutation {\n    singleUpload(file: Upload!): File!\n    deleteFile(id: ID!): Boolean!\n  }\n<\/code>;\n\nmodule.exports = typeDefs;<\/code><\/pre>\n<p>Burada:<br \/>\n*   <code>Upload<\/code>: Dosya y\u00fcklemeleri i\u00e7in \u00f6zel bir scalar tip.<br \/>\n*   <code>File<\/code>: Y\u00fcklenen bir dosyan\u0131n metadata&#8217;s\u0131n\u0131 temsil eden bir tip. <code>id<\/code>, <code>filename<\/code>, <code>mimetype<\/code>, <code>encoding<\/code>, <code>url<\/code> (dosyaya eri\u015fim yolu) ve <code>size<\/code> (boyut) i\u00e7erir.<br \/>\n*   <code>Query<\/code>: <code>files<\/code> sorgusu ile t\u00fcm y\u00fcklenen dosyalar\u0131 listeleriz.<br \/>\n*   <code>Mutation<\/code>:<br \/>\n    *   <code>singleUpload<\/code>: Tek bir dosya y\u00fcklemek i\u00e7in kullan\u0131l\u0131r. <code>Upload<\/code> tipinde bir <code>file<\/code> arg\u00fcman\u0131 al\u0131r ve y\u00fcklenen dosyan\u0131n <code>File<\/code> tipinde metadata&#8217;s\u0131n\u0131 d\u00f6ner.<br \/>\n    *   <code>deleteFile<\/code>: Belirli bir dosyay\u0131 silmek i\u00e7in kullan\u0131l\u0131r. <code>id<\/code> arg\u00fcman\u0131 al\u0131r ve i\u015flemin ba\u015far\u0131l\u0131 olup olmad\u0131\u011f\u0131n\u0131 belirten bir <code>Boolean<\/code> d\u00f6ner.<\/p>\n<h4>Resolvers Uygulamas\u0131<\/h4>\n<p>Resolvers, \u015femadaki sorgu ve mutasyonlar\u0131 ger\u00e7ek veri ve mant\u0131kla e\u015fle\u015ftirir. Dosya y\u00fckleme ve depolama i\u00e7in <code>graphql-upload<\/code>&#8216;dan gelen <code>processUpload<\/code> fonksiyonunu kullanaca\u011f\u0131z. Dosyalar\u0131 yerel olarak <code>uploads<\/code> dizinine kaydedece\u011fiz.<\/p>\n<p><code>src\/resolvers.js<\/code>:<\/p>\n<pre><code class=\"language-javascript\">const { GraphQLUpload } = require('graphql-upload');\nconst path = require('path');\nconst { createWriteStream, unlink } = require('fs');\nconst shortid = require('shortid');\n\n\/\/ Basit bir bellek i\u00e7i dosya deposu (ger\u00e7ek uygulamada veritaban\u0131 kullan\u0131lmal\u0131)\nconst files = [];\n\nconst storeUpload = async ({ stream, filename, mimetype, encoding }) => {\n  const id = shortid.generate();\n  const fileExtension = path.extname(filename);\n  const newFilename = <code>${id}${fileExtension}<\/code>;\n  const uploadDir = path.join(__dirname, '..\/uploads');\n  const filePath = path.join(uploadDir, newFilename);\n  const fileUrl = <code>\/uploads\/${newFilename}<\/code>; \/\/ Frontend'den eri\u015fim i\u00e7in URL\n\n  \/\/ Dosyay\u0131 diske yaz\n  await new Promise((resolve, reject) =>\n    stream\n      .pipe(createWriteStream(filePath))\n      .on('finish', resolve)\n      .on('error', reject)\n  );\n\n  return { id, filename: newFilename, mimetype, encoding, url: fileUrl, filePath };\n};\n\nconst resolvers = {\n  Upload: GraphQLUpload,\n\n  Query: {\n    hello: () => 'Merhaba GraphQL Dosya Y\u00fckleme!',\n    files: () => files.map(file => ({ ...file, url: file.url })),\n  },\n\n  Mutation: {\n    singleUpload: async (parent, { file }) => {\n      const { createReadStream, filename, mimetype, encoding } = await file;\n      const stream = createReadStream();\n      const storedFile = await storeUpload({ stream, filename, mimetype, encoding });\n      \n      \/\/ Dosya boyutunu eklemek i\u00e7in stream'i yeniden okuyabiliriz veya ba\u015fka bir y\u00f6ntem kullanabiliriz.\n      \/\/ Basitlik ad\u0131na burada boyut bilgisini atl\u0131yoruz veya varsay\u0131lan bir de\u011fer veriyoruz.\n      \/\/ Ger\u00e7ek uygulamada dosya boyutunu dosya sisteminden okuyabilirsiniz.\n      const stats = await new Promise((resolve, reject) => {\n        fs.stat(storedFile.filePath, (err, stats) => {\n          if (err) reject(err);\n          resolve(stats);\n        });\n      });\n      storedFile.size = stats.size;\n\n      files.push(storedFile); \/\/ Bellek i\u00e7i depoya ekle\n      return storedFile;\n    },\n    deleteFile: async (parent, { id }) => {\n      const fileIndex = files.findIndex(f => f.id === id);\n      if (fileIndex === -1) {\n        return false; \/\/ Dosya bulunamad\u0131\n      }\n      const fileToDelete = files[fileIndex];\n\n      \/\/ Yerel dosyay\u0131 sil\n      await new Promise((resolve, reject) => {\n        unlink(fileToDelete.filePath, (err) => {\n          if (err) reject(err);\n          resolve();\n        });\n      });\n\n      files.splice(fileIndex, 1); \/\/ Bellek i\u00e7i depodan kald\u0131r\n      return true;\n    },\n  },\n};\n\nmodule.exports = resolvers;<\/code><\/pre>\n<p><strong>Not:<\/strong> Yukar\u0131daki <code>files<\/code> dizisi, dosyalar\u0131n metadata&#8217;s\u0131n\u0131 bellekte tutan basit bir yap\u0131d\u0131r. Ger\u00e7ek bir uygulamada bu verileri bir veritaban\u0131nda (MongoDB, PostgreSQL vb.) saklaman\u0131z gerekir. <code>filePath<\/code> alan\u0131, dosya silme i\u015flemi i\u00e7in gereklidir.<\/p>\n<h4>Sunucu Kurulumu<\/h4>\n<p>Express uygulamas\u0131n\u0131 ve Apollo Server&#8217;\u0131 yap\u0131land\u0131ral\u0131m. <code>graphql-upload<\/code>&#8216;\u0131n middleware&#8217;ini Express&#8217;e eklemeyi unutmay\u0131n. Ayr\u0131ca, y\u00fcklenen dosyalar\u0131n sunulabilmesi i\u00e7in bir statik dosya sunucu middleware&#8217;i eklemeliyiz.<\/p>\n<p><code>src\/index.js<\/code>:<\/p>\n<pre><code class=\"language-javascript\">const express = require('express');\nconst { ApolloServer } = require('apollo-server-express');\nconst { graphqlUploadExpress } = require('graphql-upload');\nconst typeDefs = require('.\/schema');\nconst resolvers = require('.\/resolvers');\nconst path = require('path');\nconst fs = require('fs');\n\nasync function startApolloServer() {\n  const app = express();\n\n  \/\/ Y\u00fcklenen dosyalar\u0131n depolanaca\u011f\u0131 dizini olu\u015ftur\n  const uploadDir = path.join(__dirname, '..\/uploads');\n  if (!fs.existsSync(uploadDir)) {\n    fs.mkdirSync(uploadDir);\n  }\n\n  \/\/ GraphQL dosya y\u00fckleme middleware'ini etkinle\u015ftir\n  app.use(graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 })); \/\/ Maksimum 10MB dosya boyutu\n\n  const server = new ApolloServer({\n    typeDefs,\n    resolvers,\n    uploads: false, \/\/ graphqlUploadExpress zaten dosya i\u015fleme yap\u0131yor\n  });\n\n  await server.start();\n  server.applyMiddleware({ app });\n\n  \/\/ Y\u00fcklenen dosyalar\u0131 statik olarak sun\n  app.use('\/uploads', express.static(uploadDir));\n\n  const PORT = process.env.PORT || 4000;\n\n  app.listen(PORT, () => {\n    console.log(<code>  Sunucu http:\/\/localhost:${PORT}${server.graphqlPath} adresinde \u00e7al\u0131\u015f\u0131yor<\/code>);\n    console.log(<code>  Dosyalar http:\/\/localhost:${PORT}\/uploads\/ adresinden eri\u015filebilir<\/code>);\n  });\n}\n\nstartApolloServer();<\/code><\/pre>\n<p>Art\u0131k <code>npm run dev<\/code> komutu ile arka ucu \u00e7al\u0131\u015ft\u0131rabilirsiniz. Apollo Studio veya GraphiQL aray\u00fcz\u00fcnden sorgular\u0131n\u0131z\u0131 test edebilirsiniz.<\/p>\n<h3>\u00d6n Y\u00fcz Uygulamas\u0131 (Vue.js)<\/h3>\n<h4>Vue Projesi Kurulumu<\/h4>\n<p>Vue CLI kullanarak yeni bir Vue projesi olu\u015ftural\u0131m:<\/p>\n<pre><code class=\"language-bash\">vue create graphql-file-upload-frontend\ncd graphql-file-upload-frontend\nnpm install vue-apollo graphql apollo-client apollo-link-http apollo-cache-inmemory apollo-upload-client graphql-tag<\/code><\/pre>\n<h4>GraphQL \u0130stemcisi Kurulumu<\/h4>\n<p><code>main.js<\/code> veya ayr\u0131 bir <code>apollo.js<\/code> dosyas\u0131nda Apollo Client&#8217;\u0131 yap\u0131land\u0131rmam\u0131z gerekiyor. \u00d6zellikle <code>apollo-upload-client<\/code>&#8216;\u0131 kullanarak dosya y\u00fcklemeyi desteklemeliyiz.<\/p>\n<p><code>src\/apollo.js<\/code>:<\/p>\n<pre><code class=\"language-javascript\">import Vue from 'vue';\nimport VueApollo from 'vue-apollo';\nimport { ApolloClient } from 'apollo-client';\nimport { createHttpLink } from 'apollo-link-http';\nimport { InMemoryCache } from 'apollo-cache-inmemory';\nimport { createUploadLink } from 'apollo-upload-client';\n\nVue.use(VueApollo);\n\n\/\/ HTTP ba\u011flant\u0131s\u0131 olu\u015ftur (dosya y\u00fckleme i\u00e7in \u00f6zel link kullanaca\u011f\u0131z)\n\/\/ const httpLink = createHttpLink({\n\/\/   uri: 'http:\/\/localhost:4000\/graphql',\n\/\/ });\n\n\/\/ Dosya y\u00fckleme i\u00e7in \u00f6zel link olu\u015ftur\nconst uploadLink = createUploadLink({\n  uri: 'http:\/\/localhost:4000\/graphql',\n});\n\n\/\/ Cache olu\u015ftur\nconst cache = new InMemoryCache();\n\n\/\/ Apollo Client \u00f6rne\u011fi olu\u015ftur\nconst apolloClient = new ApolloClient({\n  link: uploadLink, \/\/ Dosya y\u00fckleme linkini kullan\n  cache,\n});\n\nconst apolloProvider = new VueApollo({\n  defaultClient: apolloClient,\n});\n\nexport default apolloProvider;<\/code><\/pre>\n<p><code>src\/main.js<\/code>:<\/p>\n<pre><code class=\"language-javascript\">import Vue from 'vue';\nimport App from '.\/App.vue';\nimport apolloProvider from '.\/apollo'; \/\/ Apollo sa\u011flay\u0131c\u0131s\u0131n\u0131 import et\n\nVue.config.productionTip = false;\n\nnew Vue({\n  apolloProvider, \/\/ Apollo sa\u011flay\u0131c\u0131s\u0131n\u0131 Vue \u00f6rne\u011fine ekle\n  render: h => h(App),\n}).$mount('#app');<\/code><\/pre>\n<h4>Dosya Y\u00fckleme Bile\u015feni<\/h4>\n<p>Bir dosya y\u00fckleme bile\u015feni olu\u015ftural\u0131m. Bu bile\u015fen, bir dosya se\u00e7ici (<code><input type=\"file\"><\/code>) ve bir y\u00fckleme d\u00fc\u011fmesi i\u00e7erecektir.<\/p>\n<p><code>src\/components\/FileUpload.vue<\/code>:<\/p>\n<pre><code class=\"language-vue\"><template>\n  <div>\n    <h2>Dosya Y\u00fckle<\/h2>\n    <input type=\"file\" @change=\"onFileSelected\" \/>\n    <button @click=\"uploadFile\" :disabled=\"!selectedFile\">Y\u00fckle<\/button>\n    <p v-if=\"uploading\">Y\u00fckleniyor...<\/p>\n    <p v-if=\"uploadError\" style=\"color: red;\">Hata: {{ uploadError }}<\/p>\n    <p v-if=\"uploadedFile\">Y\u00fcklendi: {{ uploadedFile.filename }}<\/p>\n  <\/div>\n<\/template>\n\n<script>\nimport gql from 'graphql-tag';\n\nconst SINGLE_UPLOAD_MUTATION = gql<code>\n  mutation SingleUpload($file: Upload!) {\n    singleUpload(file: $file) {\n      id\n      filename\n      mimetype\n      encoding\n      url\n      size\n    }\n  }\n<\/code>;\n\nexport default {\n  name: 'FileUpload',\n  data() {\n    return {\n      selectedFile: null,\n      uploading: false,\n      uploadError: null,\n      uploadedFile: null,\n    };\n  },\n  methods: {\n    onFileSelected(event) {\n      this.selectedFile = event.target.files[0];\n      this.uploadError = null;\n      this.uploadedFile = null;\n    },\n    async uploadFile() {\n      if (!this.selectedFile) {\n        alert('L\u00fctfen bir dosya se\u00e7in.');\n        return;\n      }\n\n      this.uploading = true;\n      this.uploadError = null;\n\n      try {\n        const { data } = await this.$apollo.mutate({\n          mutation: SINGLE_UPLOAD_MUTATION,\n          variables: {\n            file: this.selectedFile,\n          },\n          \/\/ Y\u00fckleme sonras\u0131 \u00f6nbelle\u011fi g\u00fcncellemek i\u00e7in\n          update: (store, { data: { singleUpload } }) => {\n            const data = store.readQuery({ query: gql<code>\n              query {\n                files {\n                  id\n                  filename\n                  mimetype\n                  encoding\n                  url\n                  size\n                }\n              }\n            <\/code>});\n            data.files.push(singleUpload);\n            store.writeQuery({ query: gql<code>\n              query {\n                files {\n                  id\n                  filename\n                  mimetype\n                  encoding\n                  url\n                  size\n                }\n              }\n            <\/code>, data });\n          },\n        });\n        this.uploadedFile = data.singleUpload;\n        this.$emit('fileUploaded'); \/\/ Dosya y\u00fcklendi\u011finde \u00fcst bile\u015fene haber ver\n      } catch (error) {\n        console.error('Dosya y\u00fckleme hatas\u0131:', error);\n        this.uploadError = error.message;\n      } finally {\n        this.uploading = false;\n        this.selectedFile = null; \/\/ Se\u00e7ilen dosyay\u0131 s\u0131f\u0131rla\n        event.target.value = null; \/\/ Input'u s\u0131f\u0131rla\n      }\n    },\n  },\n};\n<\/script><\/code><\/pre>\n<h4>Dosya Listeleme Bile\u015feni<\/h4>\n<p>Y\u00fcklenen dosyalar\u0131 sunucudan \u00e7ekip listeleyen bir bile\u015fen olu\u015ftural\u0131m.<\/p>\n<p><code>src\/components\/FileList.vue<\/code>:<\/p>\n<pre><code class=\"language-vue\"><template>\n  <div>\n    <h2>Y\u00fcklenen Dosyalar<\/h2>\n    <p v-if=\"$apollo.loading\">Dosyalar y\u00fckleniyor...<\/p>\n    <p v-if=\"files &#038;&#038; files.length === 0\">Hen\u00fcz dosya y\u00fcklenmedi.<\/p>\n    <ul v-else>\n      <li v-for=\"file in files\" :key=\"file.id\">\n        <a :href=\"<code>http:\/\/localhost:4000${file.url}<\/code>\" target=\"_blank\">{{ file.filename }}<\/a>\n        ({{ (file.size \/ 1024 \/ 1024).toFixed(2) }} MB)\n        <button @click=\"deleteFile(file.id)\">Sil<\/button>\n      <\/li>\n    <\/ul>\n    <p v-if=\"deleteError\" style=\"color: red;\">Silme Hatas\u0131: {{ deleteError }}<\/p>\n  <\/div>\n<\/template>\n\n<script>\nimport gql from 'graphql-tag';\n\nconst FILES_QUERY = gql<code>\n  query {\n    files {\n      id\n      filename\n      mimetype\n      encoding\n      url\n      size\n    }\n  }\n<\/code>;\n\nconst DELETE_FILE_MUTATION = gql<code>\n  mutation DeleteFile($id: ID!) {\n    deleteFile(id: $id)\n  }\n<\/code>;\n\nexport default {\n  name: 'FileList',\n  apollo: {\n    files: {\n      query: FILES_QUERY,\n    },\n  },\n  data() {\n    return {\n      deleteError: null,\n    };\n  },\n  methods: {\n    async deleteFile(id) {\n      this.deleteError = null;\n      try {\n        await this.$apollo.mutate({\n          mutation: DELETE_FILE_MUTATION,\n          variables: { id },\n          \/\/ Silme sonras\u0131 \u00f6nbelle\u011fi g\u00fcncellemek i\u00e7in\n          update: (store, { data: { deleteFile } }) => {\n            if (deleteFile) {\n              const data = store.readQuery({ query: FILES_QUERY });\n              data.files = data.files.filter(file => file.id !== id);\n              store.writeQuery({ query: FILES_QUERY, data });\n            }\n          },\n        });\n      } catch (error) {\n        console.error('Dosya silme hatas\u0131:', error);\n        this.deleteError = error.message;\n      }\n    },\n  },\n};\n<\/script><\/code><\/pre>\n<h4>Ana Uygulama Bile\u015feni<\/h4>\n<p><code>App.vue<\/code> bile\u015feninde bu iki bile\u015feni bir araya getirelim.<\/p>\n<p><code>src\/App.vue<\/code>:<\/p>\n<pre><code class=\"language-vue\"><template>\n  <div id=\"app\">\n    \n    <FileUpload @fileUploaded=\"refetchFiles\" \/>\n    <hr \/>\n    <FileList ref=\"fileList\" \/>\n  <\/div>\n<\/template>\n\n<script>\nimport FileUpload from '.\/components\/FileUpload.vue';\nimport FileList from '.\/components\/FileList.vue';\n\nexport default {\n  name: 'App',\n  components: {\n    FileUpload,\n    FileList,\n  },\n  methods: {\n    refetchFiles() {\n      \/\/ FileList bile\u015fenindeki dosyalar\u0131 yeniden \u00e7ekmek i\u00e7in\n      \/\/ Bu, Apollo Client'\u0131n \u00f6nbellek g\u00fcncellemesi sayesinde genellikle otomatik olur.\n      \/\/ Ancak manuel tetiklemek isterseniz:\n      this.$refs.fileList.$apollo.queries.files.refetch();\n    },\n  },\n};\n<\/script>\n\n<style>\n#app {\n  font-family: Avenir, Helvetica, Arial, sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-align: center;\n  color: #2c3e50;\n  margin-top: 60px;\n}\n<\/style><\/code><\/pre>\n<p>Art\u0131k <code>npm run serve<\/code> komutu ile \u00f6n y\u00fcz uygulamas\u0131n\u0131 \u00e7al\u0131\u015ft\u0131rabilirsiniz. Uygulaman\u0131zda dosya y\u00fckleme ve listeleme i\u015flevlerinin \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 g\u00f6rmelisiniz.<\/p>\n<h3>Geli\u015fmi\u015f Konular ve En \u0130yi Uygulamalar<\/h3>\n<h4>G\u00fcvenlik<\/h4>\n<p>*   <strong>Kimlik Do\u011frulama ve Yetkilendirme:<\/strong> Ger\u00e7ek bir uygulamada, dosyalar\u0131 kimlerin y\u00fckleyebilece\u011fini, g\u00f6r\u00fcnt\u00fcleyebilece\u011fini veya silebilece\u011fini kontrol etmek i\u00e7in kullan\u0131c\u0131 kimlik do\u011frulama (JWT, OAuth vb.) ve yetkilendirme (rol tabanl\u0131 eri\u015fim kontrol\u00fc) mekanizmalar\u0131 eklemelisiniz. GraphQL resolvers&#8217;\u0131n\u0131zda bu kontrolleri uygulamal\u0131s\u0131n\u0131z.<br \/>\n*   <strong>Dosya T\u00fcr\u00fc ve Boyut Do\u011frulamas\u0131:<\/strong> K\u00f6t\u00fc niyetli dosyalar\u0131n y\u00fcklenmesini \u00f6nlemek i\u00e7in sunucu taraf\u0131nda dosya t\u00fcr\u00fcn\u00fc (MIME tipi) ve boyutunu mutlaka do\u011frulay\u0131n. <code>graphql-upload<\/code> ve Express middleware&#8217;leri (\u00f6rn. <code>graphqlUploadExpress<\/code>) bu konuda yard\u0131mc\u0131 olabilir.<br \/>\n*   <strong>Dosya Ad\u0131 Sanitizasyonu:<\/strong> Y\u00fcklenen dosya adlar\u0131n\u0131 g\u00fcvenlik a\u00e7\u0131klar\u0131n\u0131 (path traversal gibi) \u00f6nlemek i\u00e7in temizleyin.<br \/>\n*   <strong>Vir\u00fcs Taramas\u0131:<\/strong> Hassas uygulamalarda, y\u00fcklenen dosyalar\u0131n vir\u00fcs taramas\u0131ndan ge\u00e7irilmesi d\u00fc\u015f\u00fcn\u00fclebilir.<\/p>\n<h4>Hata Y\u00f6netimi<\/h4>\n<p>Hem \u00f6n y\u00fczde hem de arka u\u00e7ta kapsaml\u0131 hata y\u00f6netimi uygulay\u0131n. GraphQL&#8217;in hata yan\u0131tlar\u0131n\u0131 uygun \u015fekilde i\u015fleyin ve kullan\u0131c\u0131ya anlaml\u0131 geri bildirimler sa\u011flay\u0131n. Sunucu taraf\u0131nda loglama mekanizmalar\u0131 kurun.<\/p>\n<h4>\u00d6l\u00e7eklenebilirlik ve Depolama<\/h4>\n<p>*   <strong>Bulut Depolama:<\/strong> \u00dcretim ortamlar\u0131nda yerel dosya sistemi yerine Amazon S3, Google Cloud Storage veya Azure Blob Storage gibi bulut depolama hizmetleri kullan\u0131n. Bu hizmetler, y\u00fcksek eri\u015filebilirlik, dayan\u0131kl\u0131l\u0131k ve \u00f6l\u00e7eklenebilirlik sunar.<br \/>\n*   <strong>CDN (\u0130\u00e7erik Da\u011f\u0131t\u0131m A\u011f\u0131):<\/strong> Dosyalar\u0131 daha h\u0131zl\u0131 sunmak i\u00e7in bir CDN kullanmay\u0131 d\u00fc\u015f\u00fcn\u00fcn. CDN&#8217;ler, dosyalar\u0131n\u0131z\u0131 co\u011frafi olarak kullan\u0131c\u0131lara yak\u0131n sunucularda \u00f6nbelle\u011fe alarak y\u00fckleme s\u00fcrelerini azalt\u0131r.<\/p>\n<h4>Performans<\/h4>\n<p>*   <strong>Tembel Y\u00fckleme (Lazy Loading):<\/strong> \u00d6zellikle \u00e7ok say\u0131da dosya veya b\u00fcy\u00fck g\u00f6rseller listelenirken, t\u00fcm dosyalar\u0131 ayn\u0131 anda y\u00fcklemek yerine, kullan\u0131c\u0131 kayd\u0131rd\u0131k\u00e7a dosyalar\u0131 y\u00fcklemek i\u00e7in tembel y\u00fckleme veya sonsuz kayd\u0131rma tekniklerini kullan\u0131n.<br \/>\n*   <strong>K\u00fc\u00e7\u00fcltme ve S\u0131k\u0131\u015ft\u0131rma:<\/strong> G\u00f6rsel gibi medya dosyalar\u0131n\u0131 y\u00fcklemeden \u00f6nce veya sonra optimize edin (boyutlar\u0131n\u0131 k\u00fc\u00e7\u00fclt\u00fcn, s\u0131k\u0131\u015ft\u0131r\u0131n).<br \/>\n*   <strong>\u00d6nbellekleme:<\/strong> GraphQL sorgular\u0131n\u0131 ve dosya metadata&#8217;s\u0131n\u0131 \u00f6nbelle\u011fe alarak performans\u0131 art\u0131rabilirsiniz.<\/p>\n<h4>Test<\/h4>\n<p>Uygulaman\u0131z\u0131n hem arka ucunu (GraphQL resolvers, dosya depolama mant\u0131\u011f\u0131) hem de \u00f6n y\u00fcz\u00fcn\u00fc (bile\u015fenler, GraphQL entegrasyonu) birim ve entegrasyon testleri ile kapsaml\u0131 bir \u015fekilde test edin.<\/p>\n<h3>Sonu\u00e7<\/h3>\n<p>Bu makalede, GraphQL ve Vue.js kullanarak temel bir dosya i\u015fleme uygulamas\u0131n\u0131n nas\u0131l geli\u015ftirilece\u011fini detayl\u0131 bir \u015fekilde inceledik. Arka u\u00e7ta Apollo Server ve <code>graphql-upload<\/code> ile dosya y\u00fckleme, listeleme ve silme mutasyonlar\u0131n\u0131 tan\u0131mlad\u0131k ve uygulad\u0131k. \u00d6n y\u00fczde ise Vue.js ve Apollo Client ile dosya se\u00e7me, y\u00fckleme ve sunucudan \u00e7ekilen dosyalar\u0131 g\u00f6r\u00fcnt\u00fcleme i\u015flevlerini geli\u015ftirdik.<\/p>\n<p>GraphQL&#8217;in tip g\u00fcvenli\u011fi ve esnek sorgulama yetenekleri, dosya metadata&#8217;s\u0131n\u0131 y\u00f6netme ve istemcinin ihtiya\u00e7 duydu\u011fu veriyi tam olarak \u00e7ekme konusunda \u00f6nemli avantajlar sunar. Vue.js&#8217;in reaktif ve bile\u015fen tabanl\u0131 yap\u0131s\u0131 ise kullan\u0131c\u0131 aray\u00fcz\u00fcn\u00fc olu\u015fturmay\u0131 ve y\u00f6netmeyi kolayla\u015ft\u0131r\u0131r.<\/p>\n<p>Ger\u00e7ek d\u00fcnya uygulamalar\u0131 i\u00e7in g\u00fcvenlik, \u00f6l\u00e7eklenebilirlik, hata y\u00f6netimi ve performans gibi geli\u015fmi\u015f konular\u0131 g\u00f6z \u00f6n\u00fcnde bulundurarak bu temel yap\u0131y\u0131 daha da geli\u015ftirmek m\u00fcmk\u00fcnd\u00fcr. Bulut depolama, CDN entegrasyonu ve kapsaml\u0131 yetkilendirme mekanizmalar\u0131, sa\u011flam ve \u00fcretim d\u00fczeyinde bir dosya y\u00f6netim sistemi olu\u015fturmak i\u00e7in at\u0131lmas\u0131 gereken sonraki ad\u0131mlard\u0131r.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\nGiri\u015f\nG\u00fcn\u00fcm\u00fcz web uygulamalar\u0131n\u0131n ayr\u0131lmaz bir par\u00e7as\u0131 olan dosya y\u00f6net","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1402],"tags":[],"class_list":{"0":"post-34819","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-vue","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\" \/>\n<meta property=\"og:description\" content=\"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? Giri\u015f G\u00fcn\u00fcm\u00fcz web uygulamalar\u0131n\u0131n ayr\u0131lmaz bir par\u00e7as\u0131 olan dosya y\u00f6net\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2025-11-22T08:40:37+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\",\"datePublished\":\"2025-11-22T08:40:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/\"},\"wordCount\":1751,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Vue\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#respond\"]}],\"copyrightYear\":\"2025\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/\",\"name\":\"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2025-11-22T08:40:37+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/","og_locale":"tr_TR","og_type":"article","og_title":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?","og_description":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? Giri\u015f G\u00fcn\u00fcm\u00fcz web uygulamalar\u0131n\u0131n ayr\u0131lmaz bir par\u00e7as\u0131 olan dosya y\u00f6net","og_url":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2025-11-22T08:40:37+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"12 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?","datePublished":"2025-11-22T08:40:37+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/"},"wordCount":1751,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Vue"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#respond"]}],"copyrightYear":"2025","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/","url":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/","name":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir? - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2025-11-22T08:40:37+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/graphql-ve-vue-ile-dosya-isleme-uygulamasi-nasil-gelistirilir\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"GraphQL ve Vue ile Dosya \u0130\u015fleme Uygulamas\u0131 Nas\u0131l Geli\u015ftirilir?"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34819","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=34819"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34819\/revisions"}],"predecessor-version":[{"id":34820,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/34819\/revisions\/34820"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=34819"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=34819"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=34819"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}