Here is some demo-quality code I once wrote which uses REST. It's very hard-coded and opinionated, but enough to steer you in the right direction. Let me know if you have any questions. You'll need to be familiar with setting up WebAPI controllers and securing them.
[Route("UploadMedia")]
[HttpPost]
public async Task<HttpResponseMessage> UploadMedia()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var root = HttpContext.Current.Server.MapPath("~/temp");
var provider = new MultipartFormDataStreamProvider(root);
var creator = new MediaCreator();
var masterDb = DatabaseHelper.MasterDatabase;
try
{
await Request.Content.ReadAsMultipartAsync(provider);
var languageCode = provider.FormData["language"];
var versioned = true;
if (string.IsNullOrEmpty(languageCode))
{
languageCode = "en";
versioned = false;
}
var language = Sitecore.Globalization.Language.Parse(languageCode);
var ids = new List<Guid>();
foreach (var file in provider.FileData)
{
var fileName = file.Headers.ContentDisposition.FileName.TrimStart('"').TrimEnd('"');
var fileKey = file.Headers.ContentDisposition.Name.TrimStart('"').TrimEnd('"');
var index = fileKey.Substring(4);
var pathKey = $"path{index}";
var path = provider.FormData[pathKey];
var nameKey = $"name{index}";
var name = provider.FormData[nameKey];
if (path == null || name == null)
{
continue;
}
var pathItem = masterDb.GetItem(path);
if (pathItem == null)
{
continue;
}
var extension = Path.GetExtension(fileName);
var localFileName = file.LocalFileName + extension;
File.Copy(file.LocalFileName, localFileName, true);
name = MakeSeoFriendly(name);
var destinationPath = $"{path}/{name}";
using (new LanguageSwitcher(language))
{
var destinationItem = (MediaItem)masterDb.GetItem(destinationPath);
if (destinationItem == null)
{
var options = new MediaCreatorOptions
{
FileBased = false,
IncludeExtensionInItemName = false,
OverwriteExisting = false,
Versioned = versioned,
Destination = destinationPath,
Database = masterDb,
Language = language
};
var mediaItem = creator.CreateFromFile(localFileName, options);
ids.Add(mediaItem.ID.Guid);
}
else
{
var media = MediaManager.GetMedia(destinationItem);
using (var fileStream = new MemoryStream(File.ReadAllBytes(localFileName)))
{
media.SetStream(fileStream, extension);
}
ids.Add(destinationItem.ID.Guid);
}
}
}
return Request.CreateResponse(HttpStatusCode.OK, ids);
}
catch (Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}
private string MakeSeoFriendly(string str)
{
if (str == null)
{
return null;
}
str = Regex.Replace(str, "[\\'\\`]", string.Empty).ToLower();
str = Regex.Replace(str, "[^a-zA-Z\\-0-9]", "-").ToLower();
str = Regex.Replace(str, "[\\-]{2,}", "-");
if (str.StartsWith("-"))
{
str = str.Substring(1);
}
if (str.EndsWith("-"))
{
str = str.TrimEnd('-');
}
return str;
}
You then consume it from your console app:
var f = new MultipartFormDataContent
{
{ new StringContent("file1"), "file1" },
{ new StringContent("/sitecore/media library/Images"), "path1" },
{ new StringContent("name of the image"), "name1" },
{ new StringContent("en"), "language" }
};
var fileContent = new StreamContent(fuImage.PostedFile.InputStream);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") {
Name = "file1",
FileName = fuImage.PostedFile.FileName
};
f.Add(fileContent);
var r = await YourRestClient.PostAsync("yourapi/UploadMedia", f);
var sitecoreIds = await r.Content.ReadAsAsync<List<Guid>>();