/// <summary> /// Uploads media (only photos). /// </summary> /// <remarks> /// <see href="https://dev.twitter.com/rest/reference/post/media/upload-init"/> /// </remarks> /// <param name="path">File path.</param> public static async Task <RequestResult> UploadMedia(string path, MeadiaUploadEventHandler uploadingCallback) { var file = new FileInfo(path); string media_type = "image/jpeg"; switch (file.Extension.ToLower()) { case ".png": media_type = "image/png"; break; case ".gif": media_type = "image/gif"; break; case ".bmp": media_type = "image/bmp"; break; } var parameters = new HttpParameterCollection(); parameters.AddFormParameter("command", "INIT"); parameters.AddFormParameter("total_bytes", file.Length.ToString()); parameters.AddFormParameter("media_type", media_type); parameters.AddFormParameter("media_category", "tweet_image"); var t = Task.Run <RequestResult>(() => { return(OAuthUtility.Post ( "https://upload.twitter.com/1.1/media/upload.json", parameters: parameters, authorization: TwitterApi.GetAuth(), contentType: "multipart/form-data" )); }); var result = await t; if (result.IsSuccessfully) { return(await TwitterApi.MeadiaUploadAppend(path, result["media_id"].ToString(), 0, uploadingCallback)); } else { return(result); } }
/// <summary> /// https://dev.twitter.com/rest/reference/post/media/upload-append /// </summary> /// <param name="path">File path.</param> /// <param name="media_id">Media id.</param> /// <param name="chunk">Chunk. Default: 0.</param> /// <param name="uploadingCallback">Uploading callback.</param> private static async Task <RequestResult> MeadiaUploadAppend(string path, string media_id, int chunk, MeadiaUploadEventHandler uploadingCallback) { var file = new FileInfo(path); bool isUploded = false; byte[] media = null; if (chunk > 0) { // multiple chunks using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.Inheritable)) using (var reader = new BinaryReader(stream)) { stream.Position = (TwitterApi.MediaUploadChunkSize * chunk); media = reader.ReadBytes(TwitterApi.MediaUploadChunkSize); isUploded = (stream.Position == stream.Length); } } else { if (file.Length <= TwitterApi.MediaUploadChunkSize) { // one chunk using (var reader = new BinaryReader(file.Open(FileMode.Open, FileAccess.Read, FileShare.Inheritable))) { media = reader.ReadBytes(Convert.ToInt32(file.Length)); isUploded = true; } } else { // multiple chunks using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.Inheritable)) using (var reader = new BinaryReader(stream)) { media = reader.ReadBytes(TwitterApi.MediaUploadChunkSize); isUploded = (stream.Position == stream.Length); } } } var parameters = new HttpParameterCollection(); parameters.AddFormParameter("command", "APPEND"); parameters.AddFormParameter("media_id", media_id); parameters.AddFormParameter("segment_index", chunk.ToString()); parameters.Add("media", Path.GetFileName(path), media); var t = Task.Run <RequestResult>(() => { return(OAuthUtility.Post ( "https://upload.twitter.com/1.1/media/upload.json", parameters: parameters, authorization: TwitterApi.GetAuth(), contentType: "multipart/form-data", streamWriteCallback: (object s, StreamWriteEventArgs e) => { int progressPercentage = 0; long totalUploaded = 0; if (chunk > 0) { totalUploaded = TwitterApi.MediaUploadChunkSize * chunk; } totalUploaded += e.TotalBytesWritten; progressPercentage = Convert.ToInt32((totalUploaded * 100) / file.Length); uploadingCallback?.Invoke(s, new ProgressChangedEventArgs(progressPercentage, null)); } )); }); var result = await t; if (!result.IsSuccessfully) { // error return(result); } if (file.Length > TwitterApi.MediaUploadChunkSize && !isUploded) { // next chunk return(await TwitterApi.MeadiaUploadAppend(path, media_id, chunk + 1, uploadingCallback)); } else { // finalize return(await TwitterApi.MeadiaUploadFinalize(path, media_id)); } }