如何使用axios上传文件到Dropbox

How to upload file to Dropbox with axios

我需要使用 axios 将文件上传到 Dropbox。这是我的代码:

const uploadToExternalService = async function uploadToExternalService(token, content) {
        try {
            let res = await axios({
                url: 'https://api-content.dropbox.com/1/files_put/auto/'+'file_name',
                method: 'put',
                // timeout: 8000,
                headers: {
                    Authorization: 'Bearer ' + token,
                    'Content-Type': 'text/plain',
                    body: content
                }
            })
            if(res.status == 200){
                // test for status you want, etc
                console.log(res.status)
            }
            if(res.status == 400){
                console.log(res)
            }
            return res.data
        }
        catch (err) {
            console.error(err);
        }
    }

uploadToExternalService(SECRET_KEY, req.file).then(res => console.log(res));

我遇到错误请求失败,状态代码为 400

您使用的是正式停用的 dropbox v1 API。为什么不使用 v2?

对于您的问题,请尝试将正文发送到 headers

之外
headers: {
  Authorization: 'Bearer ' + token,
  'Content-Type': 'text/plain'
},
body: content

更正代码:

const uploadToExternalService = async function uploadToExternalService(token, content) {
        try {
            let res = await axios({
                url: 'https://api-content.dropbox.com/1/files_put/auto/'+'file_name',
                method: 'put',
                // timeout: 8000,
                headers: {
                    Authorization: 'Bearer ' + token,
                    'Content-Type': 'text/plain'
                },
                body: content
            })
            if(res.status == 200){
                // test for status you want, etc
                console.log(res.status)
            }
            if(res.status == 400){
                console.log(res)
            }
            return res.data
        }
        catch (err) {
            console.error(err);
        }
    }

uploadToExternalService(SECRET_KEY, req.file).then(res => console.log(res));

最终我设法使用 dropbox-v2-api 找到了解决方案。希望这个答案能为其他社区成员提供一个有用的代码示例,尽管该解决方案已实施 w/o axios

import dropboxV2Api from "dropbox-v2-api";
import fs from "fs";

    // authentication
    const dropbox = dropboxV2Api.authenticate({
        token: DROPBOX_SECRET_KEY
    });

    //configuring parameters
    const params = Object.freeze({
        resource: 'files/upload',
        parameters: {
            path: '/file_name.docx'
        },
        readStream: fs.createReadStream(filePath)
        // filePath: path to the local file that we want to upload to Dropbox
    });

    let dropboxPromise = new Promise(function(resolve, reject) {
        dropbox(params, function(err, result) {
            if (err) {
                reject(err);
            } else {
                resolve(result);
            }
        });
    });

    await dropboxPromise.then(function (resultObj) {
        console.log("fileUpload_OK")
    }).catch(function(err){
        console.log(err.message)
    });

问题

Dropbox 文档中的示例 cURL 是:

curl -X POST https://content.dropboxapi.com/2/files/upload \
    --header "Authorization: Bearer " \
    --header "Dropbox-API-Arg: {\"path\": \"/Homework/math/Matrices.txt\",\"mode\": \"add\",\"autorename\": true,\"mute\": false,\"strict_conflict\": false}" \
    --header "Content-Type: application/octet-stream" \
    --data-binary @local_file.txt

--data-binary 表示 /upload 端点要求文件作为二进制数据发送。在axios中,好像是the only way to do this is with the FormData() interface.

但是,使用 FormData() 界面需要使用 Content-Type: multipart/form-data/upload 端点需要 Content-Type: application/octet-stream.

因此,我认为在这种情况下无法使用 Axios 上传。

替代解决方案

dropbox-v2-api 不是 Dropbox 的官方 API,对于上传超过 150MB 的文件,我找不到任何解释。因此,我会使用 dropbox-sdk-jsexample they give for /upload 是:

function uploadFile() {
        
      const UPLOAD_FILE_SIZE_LIMIT = 150 * 1024 * 1024;
      var ACCESS_TOKEN = document.getElementById('access-token').value;
      var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
      var fileInput = document.getElementById('file-upload');
      var file = fileInput.files[0];
      
      
      if (file.size < UPLOAD_FILE_SIZE_LIMIT) { // File is smaller than 150 Mb - use filesUpload API
        dbx.filesUpload({path: '/' + file.name, contents: file})
          .then(function(response) {
            var results = document.getElementById('results');
            var br = document.createElement("br");
            results.appendChild(document.createTextNode('File uploaded!'));
            results.appendChild(br);
            console.log(response);
          })
          .catch(function(error) {
            console.error(error);
          });
      } else { // File is bigger than 150 Mb - use filesUploadSession* API
        const maxBlob = 8 * 1000 * 1000; // 8Mb - Dropbox JavaScript API suggested max file / chunk size

        var workItems = [];     
      
        var offset = 0;

        while (offset < file.size) {
          var chunkSize = Math.min(maxBlob, file.size - offset);
          workItems.push(file.slice(offset, offset + chunkSize));
          offset += chunkSize;
        } 
          
        const task = workItems.reduce((acc, blob, idx, items) => {
          if (idx == 0) {
            // Starting multipart upload of file
            return acc.then(function() {
              return dbx.filesUploadSessionStart({ close: false, contents: blob})
                        .then(response => response.session_id)
            });          
          } else if (idx < items.length-1) {  
            // Append part to the upload session
            return acc.then(function(sessionId) {
             var cursor = { session_id: sessionId, offset: idx * maxBlob };
             return dbx.filesUploadSessionAppendV2({ cursor: cursor, close: false, contents: blob }).then(() => sessionId); 
            });
          } else {
            // Last chunk of data, close session
            return acc.then(function(sessionId) {
              var cursor = { session_id: sessionId, offset: file.size - blob.size };
              var commit = { path: '/' + file.name, mode: 'add', autorename: true, mute: false };              
              return dbx.filesUploadSessionFinish({ cursor: cursor, commit: commit, contents: blob });           
            });
          }          
        }, Promise.resolve());
        
        task.then(function(result) {
          var results = document.getElementById('results');
          results.appendChild(document.createTextNode('File uploaded!'));
        }).catch(function(error) {
          console.error(error);
        });
        
      }
      return false;
    }