コード例 #1
0
ファイル: CustomUploader.cs プロジェクト: nikeee/HolzShots
        public async override Task <UploadResult> InvokeAsync(Stream data, string suggestedFileName, string mimeType, IProgress <TransferProgress> progress, CancellationToken cancellationToken)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            Debug.Assert(UploaderInfo != null);
            Debug.Assert(UploaderInfo.Uploader != null);
            Debug.Assert(!string.IsNullOrWhiteSpace(suggestedFileName));
            Debug.Assert(!string.IsNullOrWhiteSpace(mimeType));

            // If the stream has a specific length, check if it exceeds the set maximum file size
            var mfs = UploaderInfo.Uploader.MaxFileSize;

            if (mfs.HasValue && mfs.Value > 0 && data.CanSeek)
            {
                var size = data.Length;
                if (size > mfs.Value)
                {
                    var memSize = new MemSize(mfs.Value);
                    throw new UploadException($"File is {memSize} in size, which is larger than the specified limit of {nameof(UploaderInfo.Uploader.MaxFileSize)}.");
                }
            }

            var uplInfo = UploaderInfo.Uploader;

            using var progressHandler = new ProgressMessageHandler(new HttpClientHandler());
            using var cl = new HttpClient(progressHandler);

            progressHandler.HttpSendProgress += (s, e) => progress.Report(TransferProgress.FromHttpProgressEventArgs(e));

            // Add the user-agent first, so the user can override it
            cl.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", SuggestedUserAgent);

            if (uplInfo.Headers != null)
            {
                foreach (var(header, value) in uplInfo.Headers)
                {
                    cl.DefaultRequestHeaders.TryAddWithoutValidation(header, value);
                }
            }

            var responseParser = uplInfo.ResponseParser;

            using var content = new MultipartFormDataContent();

            var postParams = uplInfo.PostParams;

            if (postParams is not null)
            {
                foreach (var(name, value) in postParams)
                {
                    content.Add(new StringContent(value), name);
                }
            }

            var fname = uplInfo.GetEffectiveFileName(suggestedFileName);

            Debug.Assert(!string.IsNullOrWhiteSpace(uplInfo.FileFormName));
            Debug.Assert(!string.IsNullOrWhiteSpace(fname));

            content.Add(new StreamContent(data), uplInfo.FileFormName, fname);

            Debug.Assert(!string.IsNullOrWhiteSpace(uplInfo.RequestUrl));

            var res = await cl.PostAsync(uplInfo.RequestUrl, content, cancellationToken).ConfigureAwait(false);

            if (!res.IsSuccessStatusCode)
            {
                throw new UploadException($"The servers of {UploaderInfo.Meta.Name} responded with the error {res.StatusCode}: \"{res.ReasonPhrase}\".");
            }

            var resStr = await res.Content.ReadAsStringAsync().ConfigureAwait(false);

            var urlTemplateSpec = responseParser.UrlTemplateSpec;

            // As the URL template is optional, we just take the entire response if it is not there
            if (urlTemplateSpec == null)
            {
                return(new UploadResult(this, resStr, DateTime.Now));
            }

            try
            {
                var imageUrl = urlTemplateSpec.Evaluate(resStr);
                Debug.Assert(!string.IsNullOrWhiteSpace(imageUrl));

                return(new UploadResult(this, imageUrl, DateTime.Now));
            }
            catch (UnableToFillTemplateException e)
            {
                throw new UploadException(e.Message, e);
            }
        }