Note that there are some explanatory texts on larger screens.

plurals
  1. POObjectDisposedException when trying to upload a file
    primarykey
    data
    text
    <p>I have this service class:</p> <pre><code>public delegate string AsyncMethodCaller(string id, HttpPostedFileBase file); public class ObjectService : IDisposable { private readonly IObjectRepository repository; private readonly IAmazonS3 client; private readonly string bucketName; private static object syncRoot = new object(); private static IDictionary&lt;string, int&gt; processStatus { get; set; } public ObjectService(string accessKey, string secretKey, string bucketName) { var credentials = new BasicAWSCredentials(accessKey, secretKey); this.bucketName = bucketName; this.client = new AmazonS3Client(credentials, RegionEndpoint.EUWest1); this.repository = new ObjectRepository(this.client, this.bucketName); if (processStatus == null) processStatus = new Dictionary&lt;string, int&gt;(); } public IList&lt;S3Object&gt; GetAll() { return this.repository.GetAll(); } public S3Object Get(string key) { return this.GetAll().Where(model =&gt; model.Key.Equals(key, StringComparison.OrdinalIgnoreCase)).SingleOrDefault(); } /// &lt;summary&gt; /// Note: You can upload objects of up to 5 GB in size in a single operation. For objects greater than 5 GB you must use the multipart upload API. /// Using the multipart upload API you can upload objects up to 5 TB each. For more information, see http://docs.aws.amazon.com/AmazonS3/latest/dev/uploadobjusingmpu.html. /// &lt;/summary&gt; /// &lt;param name="id"&gt;Unique id for tracking the upload progress&lt;/param&gt; /// &lt;param name="bucketName"&gt;The name of the bucket that the object is being uploaded to&lt;/param&gt; /// &lt;param name="file"&gt;The file that will be uploaded&lt;/param&gt; /// &lt;returns&gt;The unique id&lt;/returns&gt; public string Upload(string id, HttpPostedFileBase file) { var reader = new BinaryReader(file.InputStream); var data = reader.ReadBytes((int)file.InputStream.Length); var stream = new MemoryStream(data); var utility = new TransferUtility(client); var request = new TransferUtilityUploadRequest() { BucketName = this.bucketName, Key = file.FileName, InputStream = stream }; request.UploadProgressEvent += (sender, e) =&gt; request_UploadProgressEvent(sender, e, id); utility.Upload(request); return id; } private void request_UploadProgressEvent(object sender, UploadProgressArgs e, string id) { lock (syncRoot) { processStatus[id] = e.PercentDone; } } public void Add(string id) { lock (syncRoot) { processStatus.Add(id, 0); } } public void Remove(string id) { lock (syncRoot) { processStatus.Remove(id); } } public int GetStatus(string id) { lock (syncRoot) { if (processStatus.Keys.Count(x =&gt; x == id) == 1) { return processStatus[id]; } else { return 100; } } } public void Dispose() { this.repository.Dispose(); this.client.Dispose(); } } </code></pre> <p>and my controller looks like this:</p> <pre><code>public class _UploadController : Controller { public void StartUpload(string id, HttpPostedFileBase file) { var bucketName = CompanyProvider.CurrentCompanyId(); using (var service = new ObjectService(ConfigurationManager.AppSettings["AWSAccessKey"], ConfigurationManager.AppSettings["AWSSecretKey"], bucketName)) { service.Add(id); var caller = new AsyncMethodCaller(service.Upload); var result = caller.BeginInvoke(id, file, new AsyncCallback(CompleteUpload), caller); } } public void CompleteUpload(IAsyncResult result) { var caller = (AsyncMethodCaller)result.AsyncState; var id = caller.EndInvoke(result); } // // GET: /_Upload/GetCurrentProgress public JsonResult GetCurrentProgress(string id) { try { var bucketName = CompanyProvider.CurrentCompanyId(); this.ControllerContext.HttpContext.Response.AddHeader("cache-control", "no-cache"); using (var service = new ObjectService(ConfigurationManager.AppSettings["AWSAccessKey"], ConfigurationManager.AppSettings["AWSSecretKey"], bucketName)) { return new JsonResult { Data = new { success = true, progress = service.GetStatus(id) } }; } } catch (Exception ex) { return new JsonResult { Data = new { success = false, error = ex.Message } }; } } } </code></pre> <p>Now, I have found that sometimes, I get the error <strong>ObjectDisposedException</strong> when trying to upload a file on this line: <strong>var data = reader.ReadBytes((int)file.InputStream.Length);</strong>. I read that I should not be using the <strong>using</strong> keyword because of the asynchronous calls but it still seems to be disposing the stream.</p> <p>Can anyone tell me why?</p> <p><strong>Update 1</strong></p> <p>I have changed my controller to this: </p> <pre><code>private ObjectService service = new ObjectService(ConfigurationManager.AppSettings["AWSAccessKey"], ConfigurationManager.AppSettings["AWSSecretKey"], CompanyProvider.CurrentCompanyId()); public void StartUpload(string id, HttpPostedFileBase file) { service.Add(id); var caller = new AsyncMethodCaller(service.Upload); var result = caller.BeginInvoke(id, file, new AsyncCallback(CompleteUpload), caller); } public void CompleteUpload(IAsyncResult result) { var caller = (AsyncMethodCaller)result.AsyncState; var id = caller.EndInvoke(result); this.service.Dispose(); } </code></pre> <p>but I am still getting the error on the file.InputStream line.</p> <p><strong>Update 2</strong></p> <p>The problem seems to be with the BinaryReader. I changed the code to look like this:</p> <pre><code> var inputStream = file.InputStream; var i = inputStream.Length; var n = (int)i; using (var reader = new BinaryReader(inputStream)) { var data = reader.ReadBytes(n); var stream = new MemoryStream(data); var request = new TransferUtilityUploadRequest() { BucketName = this.bucketName, Key = file.FileName, InputStream = stream }; try { request.UploadProgressEvent += (sender, e) =&gt; request_UploadProgressEvent(sender, e, id); utility.Upload(request); } catch { file.InputStream.Dispose(); // Close our stream } } </code></pre> <p>If the upload fails and I try to re-upload the item, that is when the error is thrown. It is like the item is locked or something.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload