예제 #1
0
        public async Task <IActionResult> Upload([FromServices] ManagementServiceClient mgmt)
        {
            var context = HttpContext;
            var file    = context.Request.Form.Files["file"];

            if (file != null)
            {
                var id = await mgmt.PutBlobAsync("joyoi_online_judge_upload_" + file.FileName, file.ReadAllBytes());

                var f = new
                {
                    Id            = id,
                    Time          = DateTime.Now,
                    ContentType   = file.ContentType,
                    ContentLength = file.Length,
                    FileName      = file.GetFileName(),
                    Bytes         = file.ReadAllBytes()
                };

                return(Json(f));
            }
            else
            {
                var blob = new Base64StringFile(context.Request.Form["file"]);
                var id   = await mgmt.PutBlobAsync("joyoi_online_judge_upload_file", blob.AllBytes);

                var f = new
                {
                    Id            = id,
                    Time          = DateTime.Now,
                    ContentType   = blob.ContentType,
                    ContentLength = blob.Base64String.Length,
                    FileName      = "file",
                    Bytes         = blob.AllBytes
                };

                return(Json(f));
            }
        }
예제 #2
0
        public static IApplicationBuilder UseBlobStorage <TModel, TKey>(this IApplicationBuilder self, string path = "/scripts/jquery.pomelo.fileupload.js", string fileFormName = "file", string controller = "file", string downloadAction = "download", string uploadAction = "upload", string uploadRouteName = "FileUpload", string downloadRouteName = "FileDownload")
            where TKey : IEquatable <TKey>
            where TModel : Blob <TKey>, new()
        {
            #region Download

            var endpoint1 = new RouteHandler(async context => {
                var bs    = context.RequestServices.GetRequiredService <IBlobStorageProvider <TModel, TKey> >();
                var strId = context.GetRouteValue("id").ToString();
                object id;
                if (typeof(TKey) == typeof(short))
                {
                    id = Convert.ToInt16(strId);
                }
                else if (typeof(TKey) == typeof(int))
                {
                    id = Convert.ToInt32(strId);
                }
                else if (typeof(TKey) == typeof(long))
                {
                    id = Convert.ToInt64(strId);
                }
                else if (typeof(TKey) == typeof(Guid))
                {
                    id = Guid.Parse(strId);
                }
                else if (typeof(TKey) == typeof(string))
                {
                    id = strId;
                }
                else
                {
                    throw new NotSupportedException(typeof(TKey).FullName);
                }
                var blob = bs.Get((TKey)id);
                var auth = context.RequestServices.GetService <IBlobAccessAuthorizationProvider <TKey> >();
                if (blob == null)
                {
                    context.Response.StatusCode = 404;
                    await context.Response.WriteAsync("Not Found");
                }
                else if (auth != null && !auth.IsAbleToDownload(blob.Id))
                {
                    context.Response.StatusCode = 403;
                    await context.Response.WriteAsync("Forbidden");
                }
                else
                {
                    context.Response.ContentType = blob.ContentType;
                    context.Response.Headers["Content-length"] = blob.Bytes.Length.ToString();
                    if (blob.ContentType.IndexOf("image") < 0)
                    {
                        context.Response.Headers["Content-disposition"] = $"attachment; filename={WebUtility.UrlEncode(blob.FileName)}";
                    }
                    else
                    {
                        context.Response.Headers["Cache-Control"] = $"max-age={ 60 * 24 }";
                    }
                    context.Response.Body.Write(blob.Bytes, 0, blob.Bytes.Length);
                }
            });
            var routeBuilder1 = new RouteBuilder(self);
            routeBuilder1.DefaultHandler = endpoint1;
            routeBuilder1.MapRoute(downloadRouteName, controller + "/" + downloadAction + "/{id}");
            #endregion
            #region Upload
            self.Map("/" + controller + "/" + uploadAction, config =>
            {
                config.Run(async context =>
                {
                    var auth    = context.RequestServices.GetService <IBlobUploadAuthorizationProvider>();
                    var handler = context.RequestServices.GetService <IBlobHandler <TModel, TKey> >();
                    if (auth != null && !auth.IsAbleToUpload())
                    {
                        context.Response.StatusCode = 403;
                        await context.Response.WriteAsync("Forbidden");
                    }
                    else if (context.Request.Method == "POST")
                    {
                        var bs   = context.RequestServices.GetRequiredService <IBlobStorageProvider <TModel, TKey> >();
                        var file = context.Request.Form.Files["file"];
                        if (file != null)
                        {
                            var f = new TModel
                            {
                                Time          = DateTime.Now,
                                ContentType   = file.ContentType,
                                ContentLength = file.Length,
                                FileName      = file.GetFileName(),
                                Bytes         = file.ReadAllBytes()
                            };
                            if (handler != null)
                            {
                                f = handler.Handle(f, new Base64StringFile(f.Bytes, file.ContentType));
                            }
                            var id = bs.Set(f);
                            await context.Response.WriteAsync(Newtonsoft.Json.JsonConvert.SerializeObject(f));
                        }
                        else
                        {
                            var blob = new Base64StringFile(context.Request.Form["file"]);
                            var f    = new TModel
                            {
                                Time          = DateTime.Now,
                                ContentType   = blob.ContentType,
                                ContentLength = blob.Base64String.Length,
                                FileName      = "file",
                                Bytes         = blob.AllBytes
                            };
                            if (handler != null)
                            {
                                f = handler.Handle(f, new Base64StringFile(f.Bytes, f.Bytes.Length.ToString()));
                            }
                            var id = bs.Set(f);
                            await context.Response.WriteAsync(Newtonsoft.Json.JsonConvert.SerializeObject(f));
                        }
                    }
                    else
                    {
                        context.Response.StatusCode = 400;
                        await context.Response.WriteAsync("Bad Request");
                    }
                });
            });
            #endregion
            #region Javascript
            self.Map(path, config =>
            {
                config.Run(async context =>
                {
                    await context.Response.WriteAsync(@"(function ($, window) {
    'use strict';

    var supported = (window.File && window.FileReader && window.FileList);

    /**
     * @options
     * @param action [string] 'Where to submit uploads'
     * @param label [string] <'Drag and drop files or click to select'> 'Dropzone text'
     * @param maxQueue [int] <2> 'Number of files to simultaneously upload'
     * @param maxSize [int] <5242880> 'Max file size allowed'
     * @param postData [object] 'Extra data to post with upload'
     * @param postKey [string] <'file'> 'Key to upload file as'
     */

    var options = {
        action: '',
        label: 'Drag and drop files or click to select',
        maxQueue: 2,
        maxSize: 5242880, // 5 mb
        postData: {},
        postKey: 'file'
    };

    /**
     * @events
     * @event start.dropper ''
     * @event complete.dropper ''
     * @event fileStart.dropper ''
     * @event fileProgress.dropper ''
     * @event fileComplete.dropper ''
     * @event fileError.dropper ''
     */

    var pub = {

        /**
         * @method
         * @name defaults
         * @description Sets default plugin options
         * @param opts [object] <{}> 'Options object'
         * @example $.dropper('defaults', opts);
         */
        defaults: function (opts) {
            options = $.extend(options, opts || {});
            return $(this);
        }
    };

    /**
     * @method private
     * @name _init
     * @description Initializes plugin
     * @param opts [object] 'Initialization options'
     */
    function _init(opts) {
        var $items = $(this);

        if (supported) {
            // Settings
            opts = $.extend({}, options, opts);

            // Apply to each element
            for (var i = 0, count = $items.length; i < count; i++) {
                _build($items.eq(i), opts);
            }
        }

        return $items;
    }

    /**
     * @method private
     * @name _build
     * @description Builds each instance
     * @param $nav [jQuery object] 'Target jQuery object'
     * @param opts [object] <{}> 'Options object'
     */
    function _build($dropper, opts) {
        opts = $.extend({}, opts, $dropper.data('dropper-options'));
        $dropper.addClass('dropper');

        var data = $.extend({
            $dropper: $dropper,
            $input: $dropper.parents().find('.dropper-input'),
            queue: [],
            total: 0,
            uploading: false
        }, opts);

        $dropper.on('click.dropper', data, _onClick)
            .on('dragenter.dropper', data, _onDragEnter)
            .on('dragover.dropper', data, _onDragOver)
            .on('dragleave.dropper', data, _onDragOut)
            .on('drop.dropper', data, _onDrop)
            .data('dropper', data);

        data.$input.on('change.dropper', data, _onChange);
    }

    /**
     * @method private
     * @name _onClick
     * @description Handles click to dropzone
     * @param e [object] 'Event data'
     */
    function _onClick(e) {
        e.stopPropagation();
        e.preventDefault();

        var data = e.data;

        data.$input.trigger('click');
    }

    /**
     * @method private
     * @name _onChange
     * @description Handles change to hidden input
     * @param e [object] 'Event data'
     */
    function _onChange(e) {
        e.stopPropagation();
        e.preventDefault();

        var data = e.data,
            files = data.$input[0].files;

        if (files.length) {
            _handleUpload(data, files);
        }
    }

    /**
     * @method private
     * @name _onDragEnter
     * @description Handles dragenter to dropzone
     * @param e [object] 'Event data'
     */
    function _onDragEnter(e) {
        e.stopPropagation();
        e.preventDefault();

        var data = e.data;

        data.$dropper.addClass('dropping');
    }

    /**
     * @method private
     * @name _onDragOver
     * @description Handles dragover to dropzone
     * @param e [object] 'Event data'
     */
    function _onDragOver(e) {
        e.stopPropagation();
        e.preventDefault();

        var data = e.data;

        data.$dropper.addClass('dropping');
    }

    /**
     * @method private
     * @name _onDragOut
     * @description Handles dragout to dropzone
     * @param e [object] 'Event data'
     */
    function _onDragOut(e) {
        e.stopPropagation();
        e.preventDefault();

        var data = e.data;

        data.$dropper.removeClass('dropping');
    }

    /**
     * @method private
     * @name _onDrop
     * @description Handles drop to dropzone
     * @param e [object] 'Event data'
     */
    function _onDrop(e) {
        e.preventDefault();

        var data = e.data,
            files = e.originalEvent.dataTransfer.files;

        data.$dropper.removeClass('dropping');

        _handleUpload(data, files);
    }

    /**
     * @method private
     * @name _handleUpload
     * @description Handles new files
     * @param data [object] 'Instance data'
     * @param files [object] 'File list'
     */
    function _handleUpload(data, files) {
        var newFiles = [];

        for (var i = 0; i < files.length; i++) {
            var file = {
                index: data.total++,
                file: files[i],
                name: files[i].name,
                size: files[i].size,
                started: false,
                complete: false,
                error: false,
                transfer: null
            };

            newFiles.push(file);
            data.queue.push(file);
        }

        if (!data.uploading) {
            $(window).on('beforeunload.dropper', function () {
                return 'You have uploads pending, are you sure you want to leave this page?';
            });

            data.uploading = true;
        }

        data.$dropper.trigger('start.dropper', [newFiles]);

        _checkQueue(data);
    }

    /**
     * @method private
     * @name _checkQueue
     * @description Checks and updates file queue
     * @param data [object] 'Instance data'
     */
    function _checkQueue(data) {
        var transfering = 0,
            newQueue = [];

        // remove lingering items from queue
        for (var i in data.queue) {
            if (data.queue.hasOwnProperty(i) && !data.queue[i].complete && !data.queue[i].error) {
                newQueue.push(data.queue[i]);
            }
        }

        data.queue = newQueue;

                for (var j in data.queue) {
            if (data.queue.hasOwnProperty(j)) {
                if (!data.queue[j].started) {
                    var formData = function () {
                        var fd = new FormData();
                        fd.append(data.postKey, data.queue[j].file);
                        if (!data.postData)
                            return fd;
                        var pd = data.postData();
                        for (var k in pd) {
                            if (pd.hasOwnProperty(k)) {
                                fd.append(k, pd[k]);
                            }
                        }
                        return fd;
                    };

                    _uploadFile(data, data.queue[j], formData);
                }

                transfering++;

                if (transfering >= data.maxQueue) {
                    return;
                } else {
                    i++;
                }
            }
        }

        if (transfering === 0) {
            $(window).off('beforeunload.dropper');

            data.uploading = false;

            data.$dropper.trigger('complete.dropper');
        }
    }

    /**
     * @method private
     * @name _uploadFile
     * @description Uploads file
     * @param data [object] 'Instance data'
     * @param file [object] 'Target file'
     * @param formData [object] 'Target form'
     */
    function _uploadFile(data, file, formData) {
        if (file.size >= data.maxSize) {
            file.error = true;
            data.$dropper.trigger('fileError.dropper', [file, 'Too large']);

            _checkQueue(data);
        } else {
            file.started = true;
            file.transfer = $.ajax({
                url: data.action,
                data: formData(),
                type: 'POST',
                dataType: 'json',
                contentType: false,
                processData: false,
                cache: false,
                xhr: function () {
                    var $xhr = $.ajaxSettings.xhr();

                    if ($xhr.upload) {
                        $xhr.upload.addEventListener('progress', function (e) {
                            var percent = 0,
                                position = e.loaded || e.position,
                                total = e.total;

                            if (e.lengthComputable) {
                                percent = Math.ceil(position / total * 100);
                            }

                            data.$dropper.trigger('fileProgress.dropper', [file, percent]);
                        }, false);
                    }

                    return $xhr;
                },
                beforeSend: function (e) {
                    data.$dropper.trigger('fileStart.dropper', [file]);
                },
                success: function (response, status, jqXHR) {
                    file.complete = true;
                    data.$dropper.trigger('fileComplete.dropper', [file, response, jqXHR]);

                    _checkQueue(data);
                },
                error: function (jqXHR, status, error) {
                    file.error = true;
                    data.$dropper.trigger('fileError.dropper', [file, error]);

                    _checkQueue(data);
                }
            });
        }
    }

    $.fn.dropper = function (method) {
        if (pub[method]) {
            return pub[method].apply(this, Array.prototype.slice.call(arguments, 1));
        } else if (typeof method === 'object' || !method) {
            return _init.apply(this, arguments);
        }
        return this;
    };

    $.dropper = function (method) {
        if (method === 'defaults') {
            pub.defaults.apply(this, Array.prototype.slice.call(arguments, 1));
        }
    };
})(jQuery, window);

(function () {
    var $, Paste, createHiddenEditable, dataURLtoBlob;

    $ = window.jQuery;

    $.paste = function (pasteContainer) {
        var pm;
        if (typeof console !== 'undefined' && console !== null) {
            console.log('DEPRECATED: This method is deprecated. Please use $.fn.pastableNonInputable() instead.');
        }
        pm = Paste.mountNonInputable(pasteContainer);
        return pm._container;
    };

    $.fn.pastableNonInputable = function () {
        var el, _i, _len;
        for (_i = 0, _len = this.length; _i < _len; _i++) {
            el = this[_i];
            Paste.mountNonInputable(el);
        }
        return this;
    };

    $.fn.pastableTextarea = function () {
        var el, _i, _len;
        for (_i = 0, _len = this.length; _i < _len; _i++) {
            el = this[_i];
            Paste.mountTextarea(el);
        }
        return this;
    };

    $.fn.pastableContenteditable = function () {
        var el, _i, _len;
        for (_i = 0, _len = this.length; _i < _len; _i++) {
            el = this[_i];
            Paste.mountContenteditable(el);
        }
        return this;
    };

    dataURLtoBlob = function (dataURL, sliceSize) {
        var b64Data, byteArray, byteArrays, byteCharacters, byteNumbers, contentType, i, m, offset, slice, _ref;
        if (sliceSize == null) {
            sliceSize = 512;
        }
        if (!(m = dataURL.match(/^data\:([^\;]+)\;base64\,(.+)$/))) {
            return null;
        }
        _ref = m, m = _ref[0], contentType = _ref[1], b64Data = _ref[2];
        byteCharacters = atob(b64Data);
        byteArrays = [];
        offset = 0;
        while (offset < byteCharacters.length) {
            slice = byteCharacters.slice(offset, offset + sliceSize);
            byteNumbers = new Array(slice.length);
            i = 0;
            while (i < slice.length) {
                byteNumbers[i] = slice.charCodeAt(i);
                i++;
            }
            byteArray = new Uint8Array(byteNumbers);
            byteArrays.push(byteArray);
            offset += sliceSize;
        }
        return new Blob(byteArrays, {
            type: contentType
        });
    };

    createHiddenEditable = function () {
        return $(document.createElement('div')).attr('contenteditable', true).css({
            width: 1,
            height: 1,
            position: 'fixed',
            left: -100,
            overflow: 'hidden'
        });
    };

    Paste = (function () {
        Paste.prototype._target = null;

        Paste.prototype._container = null;

        Paste.mountNonInputable = function (nonInputable) {
            var paste;
            paste = new Paste(createHiddenEditable().appendTo(nonInputable), nonInputable);
            $(nonInputable).on('click', (function (_this) {
                return function () {
                    return paste._container.focus();
                };
            })(this));
            paste._container.on('focus', (function (_this) {
                return function () {
                    return $(nonInputable).addClass('pastable-focus');
                };
            })(this));
            return paste._container.on('blur', (function (_this) {
                return function () {
                    return $(nonInputable).removeClass('pastable-focus');
                };
            })(this));
        };

        Paste.mountTextarea = function (textarea) {
            var ctlDown, paste;
            if (-1 !== navigator.userAgent.toLowerCase().indexOf('chrome')) {
                return this.mountContenteditable(textarea);
            }
            paste = new Paste(createHiddenEditable().insertBefore(textarea), textarea);
            ctlDown = false;
            $(textarea).on('keyup', function (ev) {
                var _ref;
                if ((_ref = ev.keyCode) === 17 || _ref === 224) {
                    return ctlDown = false;
                }
            });
            $(textarea).on('keydown', function (ev) {
                var _ref;
                if ((_ref = ev.keyCode) === 17 || _ref === 224) {
                    ctlDown = true;
                }
                if (ctlDown && ev.keyCode === 86) {
                    return paste._container.focus();
                }
            });
            $(paste._target).on('pasteImage', (function (_this) {
                return function () {
                    return $(textarea).focus();
                };
            })(this));
            $(paste._target).on('pasteText', (function (_this) {
                return function () {
                    return $(textarea).focus();
                };
            })(this));
            $(textarea).on('focus', (function (_this) {
                return function () {
                    return $(textarea).addClass('pastable-focus');
                };
            })(this));
            return $(textarea).on('blur', (function (_this) {
                return function () {
                    return $(textarea).removeClass('pastable-focus');
                };
            })(this));
        };

        Paste.mountContenteditable = function (contenteditable) {
            var paste;
            paste = new Paste(contenteditable, contenteditable);
            $(contenteditable).on('focus', (function (_this) {
                return function () {
                    return $(contenteditable).addClass('pastable-focus');
                };
            })(this));
            return $(contenteditable).on('blur', (function (_this) {
                return function () {
                    return $(contenteditable).removeClass('pastable-focus');
                };
            })(this));
        };

        function Paste(_at__container, _at__target) {
            this._container = _at__container;
            this._target = _at__target;
            this._container = $(this._container);
            this._target = $(this._target).addClass('pastable');
            this._container.on('paste', (function (_this) {
                return function (ev) {
                    var clipboardData, file, item, reader, text, _i, _j, _len, _len1, _ref, _ref1, _ref2, _ref3, _results;
                    if (((_ref = ev.originalEvent) != null ? _ref.clipboardData : void 0) != null) {
                        clipboardData = ev.originalEvent.clipboardData;
                        if (clipboardData.items) {
                            _ref1 = clipboardData.items;
                            for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
                                item = _ref1[_i];
                                if (item.type.match(/^image\//)) {
                                    reader = new FileReader();
                                    reader.onload = function (event) {
                                        return _this._handleImage(event.target.result);
                                    };
                                    reader.readAsDataURL(item.getAsFile());
                                }
                                if (item.type === 'text/plain') {
                                    item.getAsString(function (string) {
                                        return _this._target.trigger('pasteText', {
                                            text: string
                                        });
                                    });
                                }
                            }
                        } else {
                            if (-1 !== Array.prototype.indexOf.call(clipboardData.types, 'text/plain')) {
                                text = clipboardData.getData('Text');
                                _this._target.trigger('pasteText', {
                                    text: text
                                });
                            }
                            _this._checkImagesInContainer(function (src) {
                                return _this._handleImage(src);
                            });
                        }
                    }
                    if (clipboardData = window.clipboardData) {
                        if ((_ref2 = (text = clipboardData.getData('Text'))) != null ? _ref2.length : void 0) {
                            return _this._target.trigger('pasteText', {
                                text: text
                            });
                        } else {
                            _ref3 = clipboardData.files;
                            _results = [];
                            for (_j = 0, _len1 = _ref3.length; _j < _len1; _j++) {
                                file = _ref3[_j];
                                _this._handleImage(URL.createObjectURL(file));
                                _results.push(_this._checkImagesInContainer(function () { }));
                            }
                            return _results;
                        }
                    }
                };
            })(this));
        }

        Paste.prototype._handleImage = function (src) {
            var loader;
            loader = new Image();
            loader.onload = (function (_this) {
                return function () {
                    var blob, canvas, ctx, dataURL;
                    canvas = document.createElement('canvas');
                    canvas.width = loader.width;
                    canvas.height = loader.height;
                    ctx = canvas.getContext('2d');
                    ctx.drawImage(loader, 0, 0, canvas.width, canvas.height);
                    dataURL = null;
                    try {
                        dataURL = canvas.toDataURL('image/png');
                        blob = dataURLtoBlob(dataURL);
                    } catch (_error) { }
                    if (dataURL) {
                        return _this._target.trigger('pasteImage', {
                            blob: blob,
                            dataURL: dataURL,
                            width: loader.width,
                            height: loader.height
                        });
                    }
                };
            })(this);
            return loader.src = src;
        };

        Paste.prototype._checkImagesInContainer = function (cb) {
            var img, timespan, _i, _len, _ref;
            timespan = Math.floor(1000 * Math.random());
            _ref = this._container.find('img');
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                img = _ref[_i];
                img['_paste_marked_' + timespan] = true;
            }
            return setTimeout((function (_this) {
                return function () {
                    var _j, _len1, _ref1, _results;
                    _ref1 = _this._container.find('img');
                    _results = [];
                    for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
                        img = _ref1[_j];
                        if (!img['_paste_marked_' + timespan]) {
                            cb(img.src);
                        }
                        _results.push($(img).remove());
                    }
                    return _results;
                };
            })(this), 1);
        };

        return Paste;

    })();

}).call(this);

(function($, undefined) {
    $.fn.getCursorPosition = function() {
        var el = $(this).get(0);
        var pos = 0;
        if ('selectionStart' in el) {
            pos = el.selectionStart;
        } else if ('selection' in document) {
            el.focus();
            var Sel = document.selection.createRange();
            var SelLength = document.selection.createRange().text.length;
            Sel.moveStart('character', -el.value.length);
            pos = Sel.text.length - SelLength;
        }
        return pos;
    }
})(jQuery);

(function($) {
    $.fn.dragDropOrPaste = function(onUploading, onUploaded, postData) {
        var obj = this;
        this.dropper({
            action: '/" + controller + "/" + uploadAction + @"',
            maxQueue: 1,
            postData: postData || null
        })
        .on('fileStart.dropper', function (file) {
            var postargs = { };
            if (postData)
            {
                var pd = postData();
                for (var x in pd)
                    postargs[x] = pd[x];
            }

            if (onUploading)
                onUploading();
        })
        .on('fileComplete.dropper', function (file, res, ret) {
            if (onUploaded)
                onUploaded(ret);
        });
        
        this.pastableTextarea();
        this.on('pasteImage', function (ev, data) {
            var pos = obj.getCursorPosition();
            var str = obj.val();
            var postargs = { };
            if (postData)
            {
                var pd = postData();
                for (var x in pd)
                    postargs[x] = pd[x];
            }
            if (onUploading)
                onUploading();
            postargs.file = data.dataURL;
            $.post('/" + controller + "/" + uploadAction + @"', postargs, function (result) {
                if (onUploaded)
                    onUploaded(result);
            }, 'json');
        });
    }
})(jQuery);");
                });
            });
            #endregion

            return(self.UseRouter(routeBuilder1.Build()));
        }