Closed chanm003 closed 6 years ago
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.
Thanks. Any plans to add this as an enhancement?
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.
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.
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)"
What is the version of SharePoint? addChunked
works for 2016/SPO, not 2013 for instance.
Using SPO. More specifically, I use Express as my local server and sp-rest-proxy to forward requests to SPO.
What version of the Proxy? I guess I added addChunked
support related frow not so long ago. Please try the latest version.
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
sp-rest-proxy@2.5.3
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. =)
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
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 .
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.
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.
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.
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.
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);
});
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.
Going to close this as answered, please reopen should you need to continue the conversation. Thanks!
Category
[ ] Enhancement
[ ] Bug
[x] Question
Version
3.0.1
Expected / Desired Behavior / Question
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!