Dropbox直接从浏览器上传文件

我试图将文件直接上传到dropbox [来自浏览器/网络应用程序],代码API上的“uploadFile”函数需要在服务器上上传文件,这给我带来麻烦,因为我不想要任何要上传到我的服务器并从那里到dropbox的文件。

$f = fopen("test.jpg", "rb"); // requires file on server $result = $dbxClient->uploadFile("test.jpg", dbx\WriteMode::add(), $f); fclose($f); 

试过这个https://github.com/dropbox/dropbox-js失望地说没有明确的文档,文档部分的许多链接都被破坏了。

我需要将文件上传到我的帐户,客户端无需登录dropbox。

任何指针都会非常感激。 寻找Ajax / JavaScript方法。

更新

我尝试了以下内容,但没有来自Dropbox的回复

HTML

  

JavaScript的

 var doUpload = function(event){ var input = event.target; var reader = new FileReader(); reader.onload = function(){ var arrayBuffer = reader.result; $.ajax({ url: "https://api-content.dropbox.com/1/files_put/auto/uploads/" + input.files[0].name, headers: { Authorization: 'Bearer ' + MyAccessToken, contentLength: file.size }, crossDomain: true, crossOrigin: true, type: 'PUT', contentType: input.files[0].type, data: arrayBuffer, dataType: 'json', processData: false, success : function(result) { $('#uploadResults').html(result); } }); } reader.readAsArrayBuffer(input.files[0]); } 

Dropbox刚刚发布了一个博客,其中包含如何执行此操作的说明。 你可以在https://blogs.dropbox.com/developers/2016/03/how-formio-uses-dropbox-as-a-file-backend-for-javascript-apps/找到它(完全披露,我写了博客文章。)

以下是如何上传文件。

 /** * Two variables should already be set. * dropboxToken = OAuth token received then signing in with OAuth. * file = file object selected in the file widget. */ var xhr = new XMLHttpRequest(); xhr.upload.onprogress = function(evt) { var percentComplete = parseInt(100.0 * evt.loaded / evt.total); // Upload in progress. Do something here with the percent complete. }; xhr.onload = function() { if (xhr.status === 200) { var fileInfo = JSON.parse(xhr.response); // Upload succeeded. Do something here with the file info. } else { var errorMessage = xhr.response || 'Unable to upload file'; // Upload failed. Do something here with the error. } }; xhr.open('POST', 'https://content.dropboxapi.com/2/files/upload'); xhr.setRequestHeader('Authorization', 'Bearer ' + dropboxToken); xhr.setRequestHeader('Content-Type', 'application/octet-stream'); xhr.setRequestHeader('Dropbox-API-Arg', JSON.stringify({ path: '/' + file.name, mode: 'add', autorename: true, mute: false })); xhr.send(file); 

然后从dropbox下载文件执行此操作。

 var downloadFile = function(evt, file) { evt.preventDefault(); var xhr = new XMLHttpRequest(); xhr.responseType = 'arraybuffer'; xhr.onload = function() { if (xhr.status === 200) { var blob = new Blob([xhr.response], {type: 'application/octet-stream'}); FileSaver.saveAs(blob, file.name, true); } else { var errorMessage = xhr.response || 'Unable to download file'; // Upload failed. Do something here with the error. } }; xhr.open('POST', 'https://content.dropboxapi.com/2/files/download'); xhr.setRequestHeader('Authorization', 'Bearer ' + dropboxToken); xhr.setRequestHeader('Dropbox-API-Arg', JSON.stringify({ path: file.path_lower })); xhr.send(); } 

FileSaver和Blob不适用于旧版浏览器,因此您可以为它们添加变通方法。

正如其他答案所述,每个上传或下载文件的会话都需要访问Dropbox令牌。 将其他人的令牌发送给用户是一个安全问题,因为拥有令牌将使他们完全控制保管箱帐户。 实现这项工作的唯一方法是让每个人使用Dropbox进行身份validation并获取自己的令牌。

在Form.io,我们已经实现了身份validation和上传/下载到我们的平台。 这使得使用dropbox作为文件后端构建Web应用程序非常容易。

“我需要将文件上传到我的帐户,客户无需登录Dropbox。”

那你真的需要做上传服务器端。 要做到这一点,客户端将意味着将访问令牌发送到浏览器,此时您的应用程序的任何用户都可以使用该访问令牌对您的帐户执行任何他们想要的操作。 (例如删除所有其他文件,上传他们的私人DVD集合等)

出于安全原因,我强烈建议您在上传服务器端执行保密访问令牌。

非常感谢@smarx的指示,我能够达到最终的解决方案。

此外,我还添加了一些额外的function,如收听上传进度,以便用户可以显示上传进度百分比。

HTML

  

JavaScript的

 var doUpload = function(event){ var input = event.target; var reader = new FileReader(); reader.onload = function(){ var arrayBuffer = reader.result; var arrayBufferView = new Uint8Array( arrayBuffer ); var blob = new Blob( [ arrayBufferView ], { type: input.files[0].type } ); var urlCreator = window.URL || window.webkitURL; var imageUrl = urlCreator.createObjectURL( blob ); $.ajax({ url: "https://api-content.dropbox.com/1/files_put/auto/YourDirectory/" + input.files[0].name, headers: { 'Authorization':'Bearer ' +YourToken, 'Content-Length':input.files[0].size }, crossDomain: true, crossOrigin: true, type: 'PUT', contentType: input.files[0].type, data: arrayBuffer, dataType: 'json', processData: false, xhr: function() { var xhr = new window.XMLHttpRequest(); //Upload progress, litsens to the upload progress //and get the upload status xhr.upload.addEventListener("progress", function(evt){ if (evt.lengthComputable) { var percentComplete = parseInt( parseFloat(evt.loaded / evt.total) * 100); //Do something with upload progress $('#uploadProgress').html(percentComplete); $('#uploadProgressBar').css('width',percentComplete+'%'); } }, false); }, beforeSend: function(){ // Things you do before sending the file // like showing the loader GIF }, success : function(result) { // Display the results from dropbox after upload // Other stuff on complete }, }); } reader.readAsArrayBuffer(input.files[0]); } 

你已经使用了PUT方法,因为我的唯一目标是上传文件,根据我对各种资源的研究( StackOverflow和zacharyvoase )一个put方法可以流式传输大文件,也就是将文件放在指定的URI上,如果文件存在的话文件必须被替换。 无法将PUT方法移动到指定URL以外的其他URL。

风险

通过在客户端使用访问令牌,您将面临风险,需要采用高安全措施来屏蔽令牌。 但是现代Web开发工具(如浏览器控制台,Firebug等)可以监控您的服务器请求,并可以查看您的访问令牌。

到目前为止给出的答案不使用Dropbox javascript SDK,我认为这可能是最好的方法。 看看这个链接:

https://github.com/dropbox/dropbox-sdk-js/blob/master/examples/javascript/upload/index.html

它提供了一个依赖于下载SDK的示例。 (编辑:在玩SDK之后我意识到它创建了一个类似于此线程中接受的答案的POST请求。但是,流行的答案省略的是在实际POST之前存在sdk做出的OPTIONS预检调用)

我还可以补充说,dropbox sdk示例中没有显示的内容是你可以将blob对象上传到dropbox; 例如,如果您想要从canvas中动态提取图像并上传它们并且不希望通过文件上载输入上载从文件系统中选择的内容,则这非常有用。

以下是我所描述的场景的简短示例:

 //code below after having included dropbox-sdk-js in your project. //Dropbox is in scope! var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN }); //numerous stack overflow examples on creating a blob from data uri var blob = dataURIToBlob(canvas.toDataUrl()); //the path here is the path of the file as it will exist on dropbox. //should be unique or you will get a 4xx error dbx.filesUpload({path: `unq_filename.png`, contents: blob}) 

upload.html

上传

upload.js

 $('#form_wizard_1 .button-submit').click(function () { var ACCESS_TOKEN ="Your token get from dropbox"; var dbx = new Dropbox({ accessToken: ACCESS_TOKEN }); var fileInput = document.getElementById('files1'); var file = fileInput.files[0]; res=dbx.filesUpload({path: '/' + file.name, contents: file}) .then(function(response) { var results = document.getElementById('results'); results.appendChild(document.createTextNode('File uploaded!')); res=response; console.log(response); }) .catch(function(error) { console.error(error); }); }