public
Last active

ServiceStack RestFiles vs WCF Web APIs port

  • Download Gist
ServiceStack_FilesService.cs
C#
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
/*
Contains the file manager implementation of ServiceStack's REST /files Web Service:
Demo: http://www.servicestack.net/RestFiles/
GitHub: https://github.com/ServiceStack/ServiceStack.Examples/
*/
 
using System;
using System.IO;
using System.Net;
using RestFiles.ServiceInterface.Support;
using RestFiles.ServiceModel;
using RestFiles.ServiceModel.Types;
using ServiceStack.Common.Web;
using ServiceStack.ServiceHost;
using ServiceStack.ServiceInterface;
using File = System.IO.File;
 
namespace RestFiles.ServiceInterface
{
public class FilesService : Service
{
public AppConfig Config { get; set; }
 
public object Get(Files request)
{
var targetFile = GetAndValidateExistingPath(request);
 
var isDirectory = Directory.Exists(targetFile.FullName);
 
if (!isDirectory && request.ForDownload)
return new HttpResult(targetFile, asAttachment: true);
 
var response = isDirectory
? new FilesResponse { Directory = GetFolderResult(targetFile.FullName) }
: new FilesResponse { File = GetFileResult(targetFile) };
 
return response;
}
 
public void Post(Files request)
{
var targetDir = GetPath(request);
 
var isExistingFile = targetDir.Exists
&& (targetDir.Attributes & FileAttributes.Directory) != FileAttributes.Directory;
 
if (isExistingFile)
throw new NotSupportedException(
"POST only supports uploading new files. Use PUT to replace contents of an existing file");
 
if (!Directory.Exists(targetDir.FullName))
Directory.CreateDirectory(targetDir.FullName);
 
foreach (var uploadedFile in base.RequestContext.Files)
{
var newFilePath = Path.Combine(targetDir.FullName, uploadedFile.FileName);
uploadedFile.SaveTo(newFilePath);
}
}
 
public void Put(Files request)
{
var targetFile = GetAndValidateExistingPath(request);
 
if (!this.Config.TextFileExtensions.Contains(targetFile.Extension))
throw new NotSupportedException("PUT Can only update text files, not: " + targetFile.Extension);
 
if (request.TextContents == null)
throw new ArgumentNullException("TextContents");
 
File.WriteAllText(targetFile.FullName, request.TextContents);
}
 
public void Delete(Files request)
{
var targetFile = GetAndValidateExistingPath(request);
File.Delete(targetFile.FullName);
}
 
private FolderResult GetFolderResult(string targetPath)
{
var result = new FolderResult();
 
foreach (var dirPath in Directory.GetDirectories(targetPath))
{
var dirInfo = new DirectoryInfo(dirPath);
 
if (this.Config.ExcludeDirectories.Contains(dirInfo.Name)) continue;
 
result.Folders.Add(new Folder
{
Name = dirInfo.Name,
ModifiedDate = dirInfo.LastWriteTimeUtc,
FileCount = dirInfo.GetFiles().Length
});
}
 
foreach (var filePath in Directory.GetFiles(targetPath))
{
var fileInfo = new FileInfo(filePath);
 
result.Files.Add(new ServiceModel.Types.File
{
Name = fileInfo.Name,
Extension = fileInfo.Extension,
FileSizeBytes = fileInfo.Length,
ModifiedDate = fileInfo.LastWriteTimeUtc,
IsTextFile = Config.TextFileExtensions.Contains(fileInfo.Extension),
});
}
 
return result;
}
 
private FileInfo GetPath(Files request)
{
return new FileInfo(Path.Combine(this.Config.RootDirectory, request.Path.GetSafePath()));
}
 
private FileInfo GetAndValidateExistingPath(Files request)
{
var targetFile = GetPath(request);
if (!targetFile.Exists && !Directory.Exists(targetFile.FullName))
throw new HttpError(HttpStatusCode.NotFound, new FileNotFoundException("Could not find: " + request.Path));
 
return targetFile;
}
 
private FileResult GetFileResult(FileInfo fileInfo)
{
var isTextFile = this.Config.TextFileExtensions.Contains(fileInfo.Extension);
 
return new FileResult
{
Name = fileInfo.Name,
Extension = fileInfo.Extension,
FileSizeBytes = fileInfo.Length,
IsTextFile = isTextFile,
Contents = isTextFile ? File.ReadAllText(fileInfo.FullName) : null,
ModifiedDate = fileInfo.LastWriteTimeUtc,
};
}
}
}
WCFWebAPI_FilesApi.cs
C#
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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
/*
Contains the file manager implementation of WCF Web APIs REST /files Web Service:
Demo: http://webapi.alexonasp.net/restfiles/
GitHub: https://github.com/AlexZeitler/WebApi.Examples/
*/
 
using System;
using System.Collections.Generic;
using System.IO;
using System.Json;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.ServiceModel.Web;
using System.Web;
using WebApi.RestFiles.Types;
using File = WebApi.RestFiles.Types.File;
 
namespace WebApi.RestFiles.Operations
{
public class FilesApi
{
readonly AppConfig _config;
 
public FilesApi(AppConfig config) {
_config = config;
}
 
public AppConfig Config {
get { return _config; }
}
 
[WebGet(UriTemplate = "{*Path}")]
public HttpResponseMessage Get(string path, HttpRequestMessage request)
{
var targetPath = Path.Combine(Config.RootDirectory, path.Replace("/","\\"));
var forDownload = false;
 
var queryString = HttpUtility.ParseQueryString(request.RequestUri.Query.ToLower());
if(queryString.AllKeys.Contains("fordownload")) {
forDownload = bool.Parse(queryString["fordownload"]);
}
 
var isDirectory = Directory.Exists(targetPath);
 
if (!isDirectory && forDownload) {
var file = new FileStream(targetPath, FileMode.Open);
var message = new HttpResponseMessage {
Content = new StreamContent(file),
};
message.Content.Headers.ContentDisposition =
new ContentDispositionHeaderValue("attachment");
 
return message;
}
 
var response = isDirectory
? new FilesResponse { Directory = GetFolderResult(targetPath) }
: new FilesResponse { File = GetFileResult(new FileInfo(targetPath)) };
return new HttpResponseMessage<FilesResponse>(response);
}
 
[WebInvoke(Method = "POST", UriTemplate = "{*Path}")]
public HttpResponseMessage Post(string path, HttpRequestMessage request) {
var targetPath = Path.Combine(Config.RootDirectory, path.Replace("/", "\\"));
 
var targetDir = new FileInfo(targetPath);
 
var isExistingFile = targetDir.Exists
&& (targetDir.Attributes & FileAttributes.Directory) != FileAttributes.Directory;
 
if (isExistingFile)
throw new NotSupportedException(
"POST only supports uploading new files. Use PUT to replace contents of an existing file");
 
if (!Directory.Exists(targetDir.FullName)) {
Directory.CreateDirectory(targetDir.FullName);
return new HttpResponseMessage(HttpStatusCode.OK);
}
 
if (request.Content.IsMimeMultipartContent()) {
 
MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider();
 
var task = request.Content.ReadAsMultipartAsync(streamProvider);
task.Wait();
 
IEnumerable<HttpContent> bodyparts = task.Result;
 
IDictionary<string, string> bodyPartFileNames = streamProvider.BodyPartFileNames;
 
foreach (var kv in bodyPartFileNames) {
var targetFilePath = Path.Combine(targetPath, Path.GetFileName(kv.Value));
System.IO.File.Copy(kv.Value, targetFilePath);
System.IO.File.Delete(kv.Value);
}
 
return new HttpResponseMessage(HttpStatusCode.OK);
}
return new HttpResponseMessage(HttpStatusCode.BadRequest);
}
 
[WebInvoke(Method = "DELETE", UriTemplate = "{*Path}")]
public HttpResponseMessage Delete(string path)
{
var targetPath = Path.Combine(Config.RootDirectory, path.Replace("/", "\\"));
 
System.IO.File.Delete(targetPath);
 
return new HttpResponseMessage(HttpStatusCode.OK);
}
 
[WebInvoke(Method = "PUT", UriTemplate = "{*Path}")]
public HttpResponseMessage Put(string path, HttpRequestMessage request)
{
var targetPath = Path.Combine(Config.RootDirectory, path.Replace("/", "\\"));
 
dynamic formContent = request.Content.ReadAsAsync<JsonValue>().Result;
var textContents = (string)formContent.TextContents;
 
if (!this.Config.TextFileExtensions.Contains(Path.GetExtension(targetPath)))
throw new NotSupportedException("PUT Can only update text files, not: " + Path.GetExtension(targetPath));
 
if (textContents == null)
throw new ArgumentNullException("TextContents");
 
System.IO.File.WriteAllText(targetPath, textContents);
 
 
return new HttpResponseMessage(HttpStatusCode.OK);
}
 
private FolderResult GetFolderResult(string targetPath) {
var result = new FolderResult();
 
foreach (var dirPath in Directory.GetDirectories(targetPath)) {
var dirInfo = new DirectoryInfo(dirPath);
 
if (Config.ExcludeDirectories.Contains(dirInfo.Name)) continue;
 
result.Folders.Add(new Folder {
Name = dirInfo.Name,
ModifiedDate = dirInfo.LastWriteTimeUtc,
FileCount = dirInfo.GetFiles().Length
});
}
 
foreach (var filePath in Directory.GetFiles(targetPath)) {
var fileInfo = new FileInfo(filePath);
 
result.Files.Add(new File {
Name = fileInfo.Name,
Extension = fileInfo.Extension,
FileSizeBytes = fileInfo.Length,
ModifiedDate = fileInfo.LastWriteTimeUtc,
IsTextFile = Config.TextFileExtensions.Contains(fileInfo.Extension),
});
}
 
return result;
}
 
private FileResult GetFileResult(FileInfo fileInfo) {
var isTextFile = this.Config.TextFileExtensions.Contains(fileInfo.Extension);
 
return new FileResult {
Name = fileInfo.Name,
Extension = fileInfo.Extension,
FileSizeBytes = fileInfo.Length,
IsTextFile = isTextFile,
Contents = isTextFile ? System.IO.File.ReadAllText(fileInfo.FullName) : null,
ModifiedDate = fileInfo.LastWriteTimeUtc,
};
}
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.