RickStrahl / MarkdownMonster

An extensible Markdown Editor, Viewer and Weblog Publisher for Windows
https://markdownmonster.west-wind.com
Other
1.58k stars 236 forks source link

WebLog: Add Option to replace image source with absolute URL in markdown after post published #442

Closed darkthread closed 5 years ago

darkthread commented 5 years ago

When using MetaWeblogApi to publish posts, I found that the images were uploaded more than once if I modified the post text and published it again. The republish process left a lot of garbage image files on blog web server.

To solve the problem, I added a option to Markdown Monster WeblogAddin. A "ReplaceImgSrcAfterPublish" setting is added to WeblogAddinConfiguration, when it's turned on, ![](someImg.png) will be replaced with ![](http://blog-server/img-folders/someImg-xxxxxx.png), the real absolute url of uploaded image. You can view the uploaded image in preview window (if you are connected to Internet) and the uploaded image file will be ignored.

Here's the POC commit: darkthread/MarkdownMonster@ea0175c

darkthread commented 5 years ago

Changing original document seems not a good idea, may be storing the uploaded images mapping in YAML metadata store is a better option. I will try it latter. This issue can be ignored.

RickStrahl commented 5 years ago

Linked Discussion:

https://support.west-wind.com/Thread5AV18LZCU.wwt

In a nutshell we're discussing whether it makes sense to replace the images with a URL when posting, effectively changing your root document. My initial though is this is not a good idea even though some other tools do this because it a) changes the original document and b) makes it messier to update an existing image later.

But after giving this some more thought - I think the way to do this might be to replace the links as an option. You mention Live Writer and I do seem to remember that it would pick up the downloaded image URL and embed it into the post effectively changing the post with the new link.

I still think that's not the behavior one would want but if the blog engine doesn't support idempotent uploads of the same file, then that option is probably the cleanest approach. With Live Writer the problem always was that it would create new image filenames each and every time it would upload so if you uploaded the same image with an update it would pollute the server with images that would never be used. This is the primary reason why I much prefer to have images uploaded each time you repost and let the server assign the image ids in a consistent way so an updated image updates an already existing image without the waste.

darkthread commented 5 years ago

Another try: darkthread/MarkdownMonster@93249ad

A property "RememberImageUploadStatus" is added to WebLogAddinConfiguration. When it's set to true, a dictionary of filename with content hash to MediaObjectInfo object returned by NewMediaObject() call, a property named as MediaObjects, is stored in YAML.

When the markdown is published more than once, there is a check logic in SendImages(). If the file name and content MD5 hash already exists in the MediaObjects dictionary, it will use the MediaObjectInfo in dictionary instead of calling NewMediaObject(), so the uploaded image can be reused and no duplicated image upload. If it's a new image file or the file name or content changed, the image file will be uploaded via NewMediaObject() and the result will be added to MediaObjects dictionary. This is similar what Live Writer did to prevent duplicated uploading, the different part is Live Write store the mapping data in its own .wpost file format.

Pros: the markdown document always keep the original content and the preview window doesn't require Internet connection.

Cons: ugly data in YAML block, Since it's a optional feature, it's OK for me if I want to avoid duplicated image files on server.

---
title: test 12345
weblogName: My Blog
postId: 636734015982601822
postDate: 2018-09-24T23:59:45.7430473+08:00
mediaObjects:
  dough-2948026_1280.jpg#JTT8SBZxq+MWExjkIJJgbg==:
    uRL: http://blog.sample.net/Posts/files/dough-2948026_1280_636734029171107682.jpg
  street-marathon-1149220_1280.jpg#nGZx/FZ4qWva2JwBqVXabA==:
    uRL: http://blog.sample.net/Posts/files/street-marathon-1149220_1280_636734029171555814.jpg
---
![](dough-2948026_1280.jpg)![](street-marathon-1149220_1280.jpg)
RickStrahl commented 5 years ago

I think the real solution is fixing mini-blog's image handling... :-)

FWIW, here's how I handle my images for Metaweblog media uploads in my own blog engine:

public mediaObjectInfo newMediaObject(object blogid, string username, string password, mediaObject mediaobject)
{
    ValidateUser(username,password);

    var imagePath = "~/images/" + DateTime.Now.Year;

    string ImagePhysicalPath = HttpContext.Current.Server.MapPath(imagePath);            
    string ImageWebPath = WebUtils.ResolveServerUrl(imagePath);

    if (mediaobject.bits != null)
    {
        MemoryStream ms = new MemoryStream(mediaobject.bits);
        Bitmap bitmap = new Bitmap(ms);

        ImagePhysicalPath = Path.Combine(ImagePhysicalPath,mediaobject.name);
        string PathOnly = Path.GetDirectoryName(ImagePhysicalPath).Replace("/","\\");
        if (!Directory.Exists(PathOnly))
            Directory.CreateDirectory(PathOnly);

        bitmap.Save(ImagePhysicalPath);

        // optimize PNG image
        if (Path.GetExtension(ImagePhysicalPath).ToLower() == ".png")
        {
            var pngOutPath = HttpContext.Current.Server.MapPath("~/") + "tools\\pngout.exe";                    
            var p = Process.Start(pngOutPath, "\"" + ImagePhysicalPath + "\" /y /kt");
            p.ErrorDataReceived += (sender, e) =>
            {
                LogManager.Current.LogError("pngOut failed", e.Data);            
            };
        }                    
    }

    mediaObjectInfo mediaInfo = new mediaObjectInfo();
    mediaInfo.url = ImageWebPath + "/" + mediaobject.name;
    mediaInfo.url = mediaInfo.url.Replace(" ", "%20");        

    return mediaInfo;
}

I write each post's images into a separate folder (or you could push to Azure blob storage etc.) so if I sent the same file up, it's overwritten.

darkthread commented 5 years ago

Got it. Thanks for the detail of implementation.

I think there are two different strategies of blog system. Miniblog and another blog system I used before (Community Server) give every uploaded image a unique filename, so you don't have to worry about file name duplication or file location, the drawback is useless files left on server. Another is like your blog engine, user organize the image files in well deigned folder structure in local machine and blog editor sychronizes the same folder structure and files to the blog server, the drawback is users have to manage the file naming and folder structure.

Since there are some blog systems choosing different strategy, may I suggest add it as a optional feature?

RickStrahl commented 5 years ago

Added support for a ReplacePostImagesWithOnlineUrls Weblog configuration option which when set replaces image URLs with absolute URLs on the server.

ca460e7f3c4aff97afa6f4a882b2cdc87cb31072