Skip to content

Instantly share code, notes, and snippets.

@mythz
Created December 27, 2011 04:49
Show Gist options
  • Save mythz/1522749 to your computer and use it in GitHub Desktop.
Save mythz/1522749 to your computer and use it in GitHub Desktop.
ServiceStack RestFiles vs WCF Web APIs port
/*
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,
};
}
}
}
/*
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,
};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment