-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathFileTransferHandler.ashx.cs
More file actions
157 lines (131 loc) · 4.81 KB
/
FileTransferHandler.ashx.cs
File metadata and controls
157 lines (131 loc) · 4.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Script.Serialization;
namespace jQueryUploadTest {
public class FileTransferHandler : IHttpHandler {
private readonly JavaScriptSerializer js = new JavaScriptSerializer();
public string StorageRoot {
get { return ConfigurationManager.AppSettings["StorageRoot"]; }
}
public bool IsReusable { get { return false; } }
public void ProcessRequest (HttpContext context) {
context.Response.AddHeader("Pragma", "no-cache");
context.Response.AddHeader("Cache-Control", "private, no-cache");
HandleMethod(context);
}
// Handle request based on method
private void HandleMethod (HttpContext context) {
switch (context.Request.HttpMethod) {
case "HEAD":
case "GET":
if (GivenFilename(context)) DeliverFile(context);
else ListCurrentFiles(context);
break;
case "POST":
case "PUT":
UploadFile(context);
break;
case "DELETE":
DeleteFile(context);
break;
case "OPTIONS":
ReturnOptions(context);
break;
default:
context.Response.ClearHeaders();
context.Response.StatusCode = 405;
break;
}
}
private static void ReturnOptions(HttpContext context) {
context.Response.AddHeader("Allow", "DELETE,GET,HEAD,POST,PUT,OPTIONS");
context.Response.StatusCode = 200;
}
// Delete file from the server
private void DeleteFile (HttpContext context) {
var filePath = StorageRoot + context.Request["f"];
if (File.Exists(filePath)) {
File.Delete(filePath);
}
}
// Upload file to the server
private void UploadFile (HttpContext context) {
var statuses = new List<FilesStatus>();
var headers = context.Request.Headers;
if (string.IsNullOrEmpty(headers["X-File-Name"])) {
UploadWholeFile(context, statuses);
} else {
UploadPartialFile(headers["X-File-Name"], context, statuses);
}
WriteJsonIframeSafe(context, statuses);
}
// Upload partial file
private void UploadPartialFile (string fileName, HttpContext context, List<FilesStatus> statuses) {
if (context.Request.Files.Count != 1) throw new HttpRequestValidationException("Attempt to upload chunked file containing more than one fragment per request");
var inputStream = context.Request.Files[0].InputStream;
var fullName = StorageRoot + Path.GetFileName(fileName);
using (var fs = new FileStream(fullName, FileMode.Append, FileAccess.Write)) {
var buffer = new byte[1024];
var l = inputStream.Read(buffer, 0, 1024);
while (l > 0) {
fs.Write(buffer, 0, l);
l = inputStream.Read(buffer, 0, 1024);
}
fs.Flush();
fs.Close();
}
statuses.Add(new FilesStatus(new FileInfo(fullName)));
}
// Upload entire file
private void UploadWholeFile (HttpContext context, List<FilesStatus> statuses) {
for (int i = 0; i < context.Request.Files.Count; i++) {
var file = context.Request.Files[i];
file.SaveAs(StorageRoot + Path.GetFileName(file.FileName));
string fullName = Path.GetFileName(file.FileName);
statuses.Add(new FilesStatus(fullName, file.ContentLength));
}
}
private void WriteJsonIframeSafe (HttpContext context, List<FilesStatus> statuses) {
context.Response.AddHeader("Vary", "Accept");
try {
if (context.Request["HTTP_ACCEPT"].Contains("application/json"))
context.Response.ContentType = "application/json";
else
context.Response.ContentType = "text/plain";
} catch {
context.Response.ContentType = "text/plain";
}
var jsonObj = js.Serialize(statuses.ToArray());
context.Response.Write(jsonObj);
}
private static bool GivenFilename (HttpContext context) {
return !string.IsNullOrEmpty(context.Request["f"]);
}
private void DeliverFile (HttpContext context) {
var filename = context.Request["f"];
var filePath = StorageRoot + filename;
if (File.Exists(filePath)) {
context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
context.Response.ContentType = "application/octet-stream";
context.Response.ClearContent();
context.Response.WriteFile(filePath);
} else
context.Response.StatusCode = 404;
}
private void ListCurrentFiles (HttpContext context) {
var files =
new DirectoryInfo(StorageRoot)
.GetFiles("*", SearchOption.TopDirectoryOnly)
.Where(f => !f.Attributes.HasFlag(FileAttributes.Hidden))
.Select(f => new FilesStatus(f))
.ToArray();
string jsonObj = js.Serialize(files);
context.Response.AddHeader("Content-Disposition", "inline; filename=\"files.json\"");
context.Response.Write(jsonObj);
context.Response.ContentType = "application/json";
}
}
}