├── README.md
└── Editor
└── Uploader.cs
/README.md:
--------------------------------------------------------------------------------
1 | This is a simple FTP uploader for Unity. An editor window allows you to specify
2 | a server and user credentials then directly build and upload your game there.
3 |
4 | Note that the ability to programmatically build a game requires Unity Pro.
5 |
--------------------------------------------------------------------------------
/Editor/Uploader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using UnityEditor;
5 | using UnityEngine;
6 |
7 | ///
8 | /// An editor extension for uploading built files directly to a (S)FTP server.
9 | ///
10 | class FTPUploader : EditorWindow
11 | {
12 | enum Protocol { FTP, SFTP }
13 |
14 | // Application info:
15 |
16 | public static readonly Version version = new Version(0, 1);
17 | const string applicationName = "Uploader";
18 |
19 | bool showMoreOptions;
20 |
21 | // Labels:
22 |
23 | GUIContent protocolLabel = new GUIContent("Protocol");
24 | GUIContent serverLabel = new GUIContent("Server");
25 | GUIContent usernameLabel = new GUIContent("User Name");
26 | GUIContent passwordLabel = new GUIContent("Password");
27 | GUIContent uploadLabel = new GUIContent("Upload");
28 | GUIContent moreOptionsLabel = new GUIContent("More Options");
29 | GUIContent pathLabel = new GUIContent("Initial Path", "The directory to upload to on the server.");
30 | GUIContent filenameLabel = new GUIContent("File Name", "The name of the .unity3d file that's created.");
31 |
32 | ///
33 | /// Initializes the window.
34 | ///
35 | [MenuItem("Window/Uploader")]
36 | static void Init ()
37 | {
38 | // Show existing open window, or make new one.
39 | Uploader window = EditorWindow.GetWindow(typeof(Uploader)) as Uploader;
40 | window.Show();
41 | }
42 |
43 | ///
44 | /// Displays the upload form.
45 | ///
46 | void OnGUI ()
47 | {
48 | // Fetch existing stored values.
49 | var protocol = (Protocol)EditorPrefs.GetInt(applicationName + " protocol", (int)Protocol.FTP);
50 | var server = EditorPrefs.GetString(applicationName + " server", "");
51 | var username = EditorPrefs.GetString(applicationName + " username", "");
52 | var password = EditorPrefs.GetString(applicationName + " password", "");
53 | var filename = EditorPrefs.GetString(applicationName + " filename", "game");
54 | var initialPath = EditorPrefs.GetString(applicationName + " initialpath", "");
55 |
56 | // Get new values.
57 | protocol = (Protocol)EditorGUILayout.EnumPopup(protocolLabel, protocol);
58 | server = EditorGUILayout.TextField(serverLabel, server);
59 | username = EditorGUILayout.TextField(usernameLabel, username);
60 | password = EditorGUILayout.PasswordField(passwordLabel, password);
61 |
62 | // More options:
63 |
64 | showMoreOptions = EditorGUILayout.Foldout(showMoreOptions, moreOptionsLabel);
65 |
66 | if (showMoreOptions) {
67 | filename = EditorGUILayout.TextField(filenameLabel, filename);
68 | initialPath = EditorGUILayout.TextField(pathLabel, initialPath);
69 | }
70 |
71 | // Store new values.
72 | EditorPrefs.SetInt(applicationName + " protocol", (int)protocol);
73 | EditorPrefs.SetString(applicationName + " server", server);
74 | EditorPrefs.SetString(applicationName + " username", username);
75 | EditorPrefs.SetString(applicationName + " password", password);
76 | EditorPrefs.SetString(applicationName + " filename", filename);
77 | EditorPrefs.SetString(applicationName + " initialpath", initialPath);
78 |
79 | filename += ".unity3d";
80 |
81 | EditorGUILayout.BeginHorizontal();
82 |
83 | GUILayout.FlexibleSpace();
84 |
85 | if (GUILayout.Button(uploadLabel)) {
86 | try {
87 | Build(filename);
88 |
89 | switch (protocol) {
90 | case Protocol.FTP:
91 | FTPUpload(filename, server, username, password, initialPath);
92 | break;
93 |
94 | case Protocol.SFTP:
95 | SFTPUpload(filename, server, username, password, initialPath);
96 | break;
97 | }
98 | } catch (Exception e) {
99 | Debug.LogError("Unable to upload game: " + e.Message);
100 | }
101 | }
102 |
103 | EditorGUILayout.EndHorizontal();
104 | }
105 |
106 | ///
107 | /// Builds the web player.
108 | ///
109 | /// The name of the file to build;
110 | static void Build (string filename)
111 | {
112 | var result = BuildPipeline.BuildPlayer(new string[] {}, filename, BuildTarget.WebPlayer, BuildOptions.Development);
113 |
114 | if (result != "") {
115 | throw new Exception("Unable to build file: " + result);
116 | }
117 | }
118 |
119 | ///
120 | /// Uploads a file through FTP.
121 | ///
122 | /// The path to the file to upload.
123 | /// The server to use.
124 | /// The username to use.
125 | /// The password to use.
126 | /// The path on the server to upload to.
127 | static void Upload (string filename, string server, string username, string password, string initialPath)
128 | {
129 | var file = new FileInfo(filename);
130 | var address = new Uri("ftp://" + server + "/" + Path.Combine(initialPath, file.Name));
131 | var request = FtpWebRequest.Create(address) as FtpWebRequest;
132 |
133 | // Upload options:
134 |
135 | // Provide credentials
136 | request.Credentials = new NetworkCredential(username, password);
137 |
138 | // Set control connection to closed after command execution
139 | request.KeepAlive = false;
140 |
141 | // Specify command to be executed
142 | request.Method = WebRequestMethods.Ftp.UploadFile;
143 |
144 | // Specify data transfer type
145 | request.UseBinary = true;
146 |
147 | // Notify server about size of uploaded file
148 | request.ContentLength = file.Length;
149 |
150 | // Set buffer size to 2KB.
151 | var bufferLength = 2048;
152 | var buffer = new byte[bufferLength];
153 | var contentLength = 0;
154 |
155 | // Open file stream to read file
156 | var fs = file.OpenRead();
157 |
158 | try {
159 | // Stream to which file to be uploaded is written.
160 | var stream = request.GetRequestStream();
161 |
162 | // Read from file stream 2KB at a time.
163 | contentLength = fs.Read(buffer, 0, bufferLength);
164 |
165 | // Loop until stream content ends.
166 | while (contentLength != 0) {
167 | //Debug.Log("Progress: " + ((fs.Position / fs.Length) * 100f));
168 | // Write content from file stream to FTP upload stream.
169 | stream.Write(buffer, 0, contentLength);
170 | contentLength = fs.Read(buffer, 0, bufferLength);
171 | }
172 |
173 | // Close file and request streams
174 | stream.Close();
175 | fs.Close();
176 | } catch (Exception e) {
177 | Debug.LogError("Error uploading file: " + e.Message);
178 | return;
179 | }
180 |
181 | Debug.Log("Upload successful.");
182 | }
183 | }
184 |
--------------------------------------------------------------------------------