/// <summary> /// Uploads a chunk of the image returning allowing for progress and cancellation /// </summary> /// <param name="uploadContext"></param> /// <returns></returns> public bool UploadChunk(UploadContext uploadContext) { // Upload a chunk of the photo/video, making sure that only a small piece // of a (possibly huge) file is read from disk into memory at a time. int chunk = Math.Min(uploadContext.ChunkSize, (int)(uploadContext.PhotoStream.Length - uploadContext.CurrentPosition)); // Safely read from the data stream. byte[] buffer = new byte[chunk]; // Buffer to store a chunk of data. int offset = 0; // Offset into buffer. int toRead = chunk; // The amount to read from the data stream. while (toRead > 0) { int read = uploadContext.PhotoStream.Read(buffer, offset, toRead); if (read <= 0) { throw new EndOfStreamException( String.Format("End of file reached with {0} bytes left to read", toRead)); } toRead -= read; offset += read; } // Write however much we read from the data stream. uploadContext.RequestStream.Write(buffer, 0, chunk); uploadContext.CurrentPosition += chunk; return(uploadContext.CurrentPosition < uploadContext.PhotoStream.Length); }
public long Upload(FileInfo fileInfo, string keyword, long albumId, string albumKey) { UploadContext uploadContext = null; long imageID; if (fileInfo.Exists == false) { throw new ArgumentException("Image does not exist: " + fileInfo.FullName); } using (FileStream fileStream = File.OpenRead(fileInfo.FullName)) { uploadContext = PrepareUpload(fileStream, fileInfo.Name, keyword, albumId, albumKey); do { // calculate the progress out of a base "100" double progressPercentage = ((double)uploadContext.CurrentPosition / (double)uploadContext.Request.ContentLength); int percentage = (int)(progressPercentage * 100); logger.Info("Uploading progress: " + percentage); } while (UploadChunk(uploadContext)); // Get response after upload. imageID = FinishUpload(uploadContext, albumId, albumKey, fileInfo.Name); } return(imageID); }
/// <summary> /// The third and final step in the photo upload process. Gets a response /// that includes the photoId from SmugMug after the upload has completed. /// </summary> /// <param name="uploadContext">The desired UploadContext.</param> /// <returns>The SmugMug photoId for the uploaded photo.</returns> public long FinishUpload(UploadContext uploadContext, long albumID, string albumKey, string fileName) { logger.Info("Verifying image upload"); string result; DateTime now = DateTime.Now; try { uploadContext.RequestStream.Close(); // set the timeout to 2 minutes // cookie.Request.Timeout = 120000; using (WebResponse response = uploadContext.Request.GetResponse()) { #if DEBUG logger.Info("Elapsed time for GetResponse: " + TimeSpan.FromTicks(DateTime.Now.Ticks - now.Ticks).Seconds); #endif using (StreamReader reader = new StreamReader(response.GetResponseStream())) { result = reader.ReadToEnd(); } response.Close(); } long imageID; var resp = JsonConvert.DeserializeObject <ImageResponse>(result); if (resp.stat == "ok") { imageID = resp.Image.id; if (imageID == 0) { logger.Error("Image upload failed, imageID = 0"); throw new SmugMugUploadException("Error uploading image, imageID = 0", null); } logger.InfoFormat("Upload successful, image id:{0} , image key:{1}", imageID, resp.Image.Key); logger.InfoFormat("Image upload end time: {0}", DateTime.Now.ToString()); } else { throw new SmugMugException(resp.code, resp.message, resp.method); } return(imageID); } catch (Exception ex) { if (ex is WebException) { WebException we = ex as WebException; logger.InfoFormat("Image upload error time: {0}", DateTime.Now.ToString()); logger.Error("Image uploading failed", we); logger.ErrorFormat("WebException status: {0}", we.Status.ToString()); logger.ErrorFormat("WebException stack trace: {0}", we.StackTrace); //// ignore receive failure errors as they seem to mean nothing and the file was uploaded //if (we.Status != WebExceptionStatus.ReceiveFailure) //{ // // in this case we want to get the real image ID // try // { // long imageID = this.GetimageID(albumID, albumKey, fileName, now); // if (imageID != 0) // { // logger.InfoFormat("Verified image was uploaded with Image ID: " + imageID); // return imageID; // } // else // { // logger.InfoFormat("Could not verify image upload"); // } // } // catch // { // } //} throw new SmugMugUploadException("Web Exception", we); } else { logger.InfoFormat("Image upload Error Time: {0}", DateTime.Now.ToString()); logger.Error("Image uploading failed", ex); throw new SmugMugUploadException("Image uploading failed", ex); } } finally { uploadContext.PhotoStream.Close(); } }
/// <summary> /// Uploads the Image to SmugMug using HTTP Post replacing the existing image /// </summary> /// <param name="stream">The stream to the image on disk.</param> /// <param name="albumID">The id for the Image to be added.</param> /// <returns>Throws an <see cref="SmugMugUploadException"/> /// if an error occurs trying to upload the Image.</remarks> public UploadContext PrepareUpload(Stream photoStream, string fileName, string keywords, long albumID, string albumKey, long imageID) { UploadContext cookie = new UploadContext(fileName); logger.InfoFormat("Preparing file for upload: {0}, album id: {1}, album key: {2}", fileName, albumID, albumKey); //int timeOut = ((int)photoStream.Length / 1024) * 1000; //cookie.Request.Timeout = timeOut; cookie.Request.Timeout = Timeout.Infinite; cookie.Request.ReadWriteTimeout = Timeout.Infinite; cookie.Request.ConnectionGroupName = Guid.NewGuid().ToString(); //cookie.Request.Headers.Add("X-Smug-SessionID", this.account.Session.id); cookie.Request.Headers.Add("X-Smug-Version", SmugMugApi.VERSION); cookie.Request.Headers.Add("X-Smug-ResponseType", "JSON"); cookie.Request.Headers.Add("X-Smug-AlbumID", albumID.ToString()); cookie.Request.Headers.Add("X-Smug-AlbumKey", albumKey); if (imageID > 0) // we are replacing the image if the ID is passed in { cookie.Request.Headers.Add("X-Smug-imageID", imageID.ToString()); } // removed this as non ascii characters we not sent //cookie.Request.Headers.Add("X-Smug-FileName", fileName); //if (String.IsNullOrEmpty(caption) == false) //{ // cookie.Request.Headers.Add("X-Smug-Caption", HttpUtility.UrlEncode(caption)); //} if (String.IsNullOrEmpty(keywords) == false) { cookie.Request.Headers.Add("X-Smug-Keywords", keywords); } // Add the authorization header string uploadURL = SmugMugApi.UploadUrl + fileName; cookie.Request.Headers.Add("Authorization", OAuthUtility.GetAuthorizationHeader(this.apiKey, this.appSecret, this.accessToken, uploadURL)); // disable HTTP/1.1 Continue // http://haacked.com/archive/2004/05/15/http-web-request-expect-100-continue.aspx ServicePointManager.Expect100Continue = false; string md5sum; MD5 md5 = new MD5CryptoServiceProvider(); byte[] hash = md5.ComputeHash(photoStream); StringBuilder buff = new StringBuilder(); foreach (byte hashByte in hash) { buff.Append(String.Format("{0:x2}", hashByte)); } md5sum = buff.ToString(); cookie.Request.Headers.Add("Content-MD5", md5sum); cookie.PhotoStream = photoStream; cookie.Request.ContentLength = cookie.PhotoStream.Length; // This option prevents uploads from being buffered into memory, avoiding OutOfMemory // exceptions on large uploads. cookie.Request.AllowWriteStreamBuffering = false; cookie.PhotoStream.Position = 0; cookie.RequestStream = cookie.Request.GetRequestStream(); cookie.ChunkSize = Math.Max((int)(cookie.PhotoStream.Length / 100), 65536); logger.InfoFormat("Image upload start time: {0}", DateTime.Now.ToString()); return(cookie); }