Skip to content
This repository has been archived by the owner on Jun 18, 2019. It is now read-only.

List Item Attachment progress callback #773

Closed
chanm003 opened this issue Apr 4, 2018 · 20 comments
Closed

List Item Attachment progress callback #773

chanm003 opened this issue Apr 4, 2018 · 20 comments

Comments

@chanm003
Copy link

chanm003 commented Apr 4, 2018

Category

[ ] Enhancement

[ ] Bug

[x] Question

Version

3.0.1

Expected / Desired Behavior / Question

var itemPnp = $pnp.sp.web.getList('/sites/dev01/Lists/Custom02').items.getById(101);
itemPnp.attachmentFiles.add('Attachment 01.txt', 'Content123')

I can see add method returns a AttachmentFileAddResult. Is it possible to subscribe to some sort of progress call back, so I can update a progress bar on my UI? If so, how would I accomplish this?

Thanks!

@koltyakov
Copy link
Collaborator

koltyakov commented Apr 4, 2018

Hey Chan,

attachmentFiles.add is a promise, it should be chained with .then and .catch.
List attachments are added in one call there are no progress callbacks for it.

For files upload (into the doc libs), there is addChunked method, this guy has progress callback. The method uploads document in multiple calls using offset chunks.

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

Thanks. Any plans to add this as an enhancement?

@koltyakov
Copy link
Collaborator

I have some concerns that chunked upload is even available for attachmentFiles in REST API itself. I should take a look into this later on.

@patrick-rodgers
Copy link
Contributor

I do not believe that is supported for list attachments. If you need attachments that are large I would recommend a document library with a lookup column back to the list item to link them. Document libraries are optimized for large files more so than attachments.

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

add() works for me but not addChunked()

Following produces a HTTP 500 error:

.rootFolder.files.addChunked(fileName, blob, (evt: ChunkedFileUploadProgressData) => {
      console.log(evt);
});

This works fine:

.rootFolder.files.add(fileName, blob);

When I catch the error from the promise and print out stack property:

"ProcessHttpClientResponseException: Error making HttpClient request in queryable: [500] Internal Server Error
    at new ProcessHttpClientResponseException (webpack-internal:///../../../../sp-pnp-js/lib/utils/exceptions.js:24:28)
    at eval (webpack-internal:///../../../../sp-pnp-js/lib/odata/core.js:47:24)
    at ZoneDelegate.invoke (webpack-internal:///../../../../zone.js/dist/zone.js:388:26)
    at Object.onInvoke (webpack-internal:///../../../core/esm5/core.js:4948:33)
    at ZoneDelegate.invoke (webpack-internal:///../../../../zone.js/dist/zone.js:387:32)
    at Zone.run (webpack-internal:///../../../../zone.js/dist/zone.js:138:43)
    at eval (webpack-internal:///../../../../zone.js/dist/zone.js:858:57)
    at ZoneDelegate.invokeTask (webpack-internal:///../../../../zone.js/dist/zone.js:421:31)
    at Object.onInvokeTask (webpack-internal:///../../../core/esm5/core.js:4939:33)
    at ZoneDelegate.invokeTask (webpack-internal:///../../../../zone.js/dist/zone.js:420:36)"

@koltyakov
Copy link
Collaborator

What is the version of SharePoint? addChunked works for 2016/SPO, not 2013 for instance.

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

Using SPO. More specifically, I use Express as my local server and sp-rest-proxy to forward requests to SPO.

@koltyakov
Copy link
Collaborator

koltyakov commented Apr 5, 2018

What version of the Proxy? I guess I added addChunked support related frow not so long ago. Please try the latest version.

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

Any reason why addChunked will not work for SP2013 on-prem?

We have NG1 code that interacts with a document' library's rootFolder/files endpoint on SP2013 production server. We use a third party NG1 service to make the request for us.

var url = document.location.protocol + '//' + document.location.hostname + ":" + document.location.port + 
			_spPageContextInfo.webServerRelativeUrl + "/_api/Web/Lists/GetByTitle('Mission Products')/RootFolder/Files/add(url='" + opts.fileName + "." + opts.fileExtension + "',overwrite=true)";

		return Upload.http({
			method: 'POST',
			url: url,
			data: opts.uploadedFile,
			binaryStringRequestBody: true,
			headers: {
				"accept": "application/json;odata=verbose",
				"X-RequestDigest": $("#__REQUESTDIGEST").val()
			},
		})
		.then(onSuccess, onError, (opts.progressCallback || onProgress));

Promise returned from Upload.http() allows us to specify three callback functions, the last of which allows us to monitor upload progress. This library is found at https://github.com/danialfarid/ng-file-upload

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

sp-rest-proxy@2.5.3

@koltyakov
Copy link
Collaborator

Add chunked support was added in 2.5.4. When somebody in the team tried it within React component targeted to SPO, then tests showed up that the same code does not work with 2013. I made an assumption that the REST API back in time didn't support it. Never dig deeper. =)

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

Do you know if addChunked internally does something different than the Upload.upload() method found here?

https://github.com/danialfarid/ng-file-upload/blob/master/src/upload.js

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

Now I have sp-rest-proxy@2.5.8, and I get further. I am uploading a 22924 byte file, so I set the chunkSize parameter to 10000. As you can see now I am receiving two ChunkedFileUploadProgressData objects, but I get an error before I get the third
lastchunk
.

@koltyakov
Copy link
Collaborator

As far as I know, Angular's $http client deals with streams, it's not a fetch/promise based. Can take a look at the implementation, I guess that some features from Angular $http client are used.

Could you please refer proxy's issue in proxy's repo? So we won't mix these two threads and projects.

Do you know if addChunked internally does something different than the Upload.upload() method found here?

Yes, addChunked works differently it manipulates with muptiple endpoints for upload continue and finish.

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

It looks like the NG1 third-party service doesn't actually make multiple HTTP requests with chunks. It simply makes a single HTTP request for the upload, but listens to events on the XmlHttpRequest:

var oReq = new XMLHttpRequest();
oReq.upload.addEventListener("progress", updateProgress);
oReq.upload.addEventListener("load", transferComplete);

Is there any way I can access these low-level details XMLHttpRequest and attach listeners? I saw that you have a Iibrary configuration section but couldn't find anything there.

@koltyakov
Copy link
Collaborator

koltyakov commented Apr 5, 2018

I'm afraid there is no such possibility in Fetch client. Yes, Fetch is a modern replacement for XMLHttpRequest, but it is a downside of simplicity - missing some features.

UPD:
Some details can be found here. If showing a progress is a must-have feature for the application, upload method should be implemented locally using raw REST and XMLHttpRequest with progress callback.

@chanm003
Copy link
Author

chanm003 commented Apr 5, 2018

Thanks for the link. I will use your suggestion for this specific use-case.

Is there a low-level utility using sp-pnp-js that allows me to easily get the X-RequestDigest? I know the fluent API handles those details for us.

@koltyakov
Copy link
Collaborator

koltyakov commented Apr 5, 2018

Can't check at the moment, but maybe something like this (blind coding alert):

import { HttpClient } from 'sp-pnp-js';
import { DigestCache } from 'sp-pnp-js/lib/net/digestcache';

const webUrl = 'https://contoso.sharepoint.com';

const digestCache = new DigestCache(new HttpClient());
digestCache.getDigest(webUrl).then(digest => {
  console.log(digest);
});

@patrick-rodgers
Copy link
Contributor

You can do that or you could just steal the code from the DigestCache class and use it in your application if you want to avoid using the library. Might be easier. Another alternative would be to show a visual element like a spinner and remove it once the file is uploaded. Attachments should be fairly small so the upload time would be pretty quick.

@patrick-rodgers
Copy link
Contributor

Going to close this as answered, please reopen should you need to continue the conversation. Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants