简体   繁体   English

Laravel 9 和 Javascript:如何下载从 Storage::download() 返回的文件

[英]Laravel 9 and Javascript: how to download a file returned from Storage::download()

DISCLAIMER: Before creating this question, I've checked here , here and here , and also checked Laravel docs.免责声明:在创建这个问题之前,我已经检查了这里这里这里,还检查了Laravel 文档。

Context语境

  • Laravel 9 full-stack Laravel 9 全栈
  • No JS framework on front-end, which means I'm using vanilla JS前端没有 JS 框架,这意味着我使用的是 vanilla JS
  • The folders on Storage are setted like this: Storage 上的文件夹设置如下:
    • storage贮存
      • app应用程序
        • public民众
          • folder1文件夹1
            • folder1A文件夹1A
            • folder1B文件夹1B
            • folder1C文件夹1C
            • etc ETC
  • The files stored in each folder1X are .pdf format and I don't know its names.每个folder1X中存储的文件都是.pdf格式,我不知道它的名字。
  • No folders are empty, nor with invalid/corrupted files.没有文件夹是空的,也没有无效/损坏的文件。

The problem问题

I have a FileController.php to download files that are inside a folder1X/ directory.我有一个FileController.php来下载folder1X/目录中的文件。 The method to download it is as follows:下载方法如下:

public function downloadFileFromStorage(Request $request): mixed
{
    $dirpath = $request->dirpath; // dirpath = public/folder1/folder1X. 

    $files = Storage::allFiles($dirpath);

    return response()->download(storage_path('app\\' . $files[0]));
}

(Note: dirpath is sent in a axios request by client and is also fetched from database on a previous request) (注意:dirpath 由客户端在 axios 请求中发送,并且也是在先前的请求中从数据库中获取的)

My Javascript CLI needs to enable the download of this file.我的 Javascript CLI 需要启用此文件的下载。 The download is enabled by clicking on a button.通过单击按钮启用下载。 The button calls downloadPDF(dirpath) which works as follows:该按钮调用downloadPDF(dirpath) ,其工作方式如下:

function downloadPDF(dirpath) {
    axios.post('/download-pdf-file', { dirpath })
        .then(
            success => {
                const url = success.data
                const a = document.createElement('a')
                a.download = 'file.pdf'
                a.href = url
                a.click()
            },
            error => {
                console.log(error.response)
            }
        )
}

But, when I run this function, I get a about:blank#blocked error.但是,当我运行这个 function 时,我得到一个about:blank#blocked错误。

Attempts尝试

  • Changed the a HTML DOM approach to a window.open(url) on client;将客户端上a HTML DOM 方法更改为window.open(url)
  • Changed response() to Storage::download($files[0], 'file-name.pdf') , and with this I also tried using Blob on client as follows:response()更改为Storage::download($files[0], 'file-name.pdf') ,为此我还尝试在客户端上使用Blob ,如下所示:
success => {
    const blob = new Blob([success.data], { type: 'application/pdf' })
    const fileURL = URL.createObjectURL(blob)
    window.openURL(fileURL)
},
  • Also mixed Blob with the a HTML DOM approach;还将Blob a HTML DOM 方法混合;
  • Changed storage_path argument to /app/public/ before concatenating to $files[0] .在连接到$files[0]之前将storage_path参数更改为/app/public/

UPDATE更新

Following tips from @BenGooding and @cengsemihsahin , I changed files to the following:根据@BenGooding@cengsemihsahin的提示,我将文件更改为以下内容:

JS JS


// FileDownload is imported on a require() at the code beginning

function downloadPDF(dirpath) {
    axios({
        url: '/download-pdf-file',
        method: 'GET',
        responseType: 'blob',
        options: {
            body: { dirpath }
        }
    }).then(
        success => {
            FileDownload(success.data, 'nota-fiscal.pdf')
        }
    )
}

PHP: PHP:


public function downloadFileFromStorage(Request $request): mixed
{
    $dirpath = $request->dirpath; // dirpath = public/folder1/folder1X. 

    $files = Storage::allFiles($dirpath);
    return Storage::download($files[0], 'filename.pdf');
}

and now it downloads a corrupted PDF that can't be opened.现在它下载了一个无法打开的损坏的 PDF。

Finally found the issue, and it was here:终于找到问题了,就在这里:

axios({
    url: '/download-pdf-file',
    method: 'GET',
    responseType: 'blob',
    options: {            // here
        body: { dirpath } // here
    }
})

Laravel's Request arrow operator -> can't fetch a GET body sent through options (At least, not on $request->key fashion; see more about it here ) thus making me download a corrupted file - it wasn't fetching any file on Laravel as it didn't get any path at all. Laravel 的请求箭头运算符->无法获取通过options发送的 GET 正文(至少,不是$request->key方式; 在这里查看更多信息)因此让我下载了一个损坏的文件 - 它没有获取任何文件在 Laravel 上,因为它根本没有得到任何路径。

Here are the solution I came with:这是我附带的解决方案:

As I want to get a file in a route that doesn't change except for the 1X at folder1X , I'm processing the path obtained and sending the 1X as a GET query param:因为我想在除了folder1X处的1X之外不会改变的路径中获取一个文件,所以我正在处理获得的路径并将1X作为 GET 查询参数发送:

let folderNumber = dirpath.split('/')
folderNumber = folderNumber[folderNumber.length].replaceAll('/', '')

axios({
    url: '/download-pdf-file?folder=',
    method: 'GET',
    responseType: 'blob'
})

This way I don't pass the whole path to back-end and it's possible to get folderNumber by using $request->query() :这样我就不会将整个路径传递给后端,并且可以使用$request->query()获取folderNumber

public function downloadFileFromStorage(Request $request): mixed
{
    $folderNumber = $request->query('folderNumber');
    $folderPath = '/public/folder1/folder' . $folderNumber . '/';
    $files = Storage::allFiles($folderPath);
        
    return Storage::download($files[0], 'file-name.pdf');
}

In a nutshell:简而言之:

  • To download files, use GET requests;要下载文件,请使用GET请求;
  • To send arguments to GET requests, use query parameters and fetch them with $request->query('keyname') (or find out another way. Good luck;);要将 arguments 发送到GET请求,请使用查询参数并使用$request->query('keyname')获取它们(或找出另一种方法。祝你好运;);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从 firebase 存储自动下载文件,而不是使用 url - Javascript - How to download a file from firebase storage automaticly and not with the url - Javascript 使用JavaScript从Firebase存储重命名或下载文件 - Rename or Download File from Firebase Storage in JavaScript 仅当网络服务返回正确的内容时,如何开始从JavaScript下载浏览器文件 - How to start browser file download from javascript, only if a web service returned correct content 如何使用javascript从stringstream内容azure blob存储下载png文件 - How to download png file from stringstream content azure blob storage using javascript 如何从 firebase 存储(Javascript,React)中的下载链接获取文件名? - How to get file name from download link in firebase storage(Javascript, React)? 如何使用javascript下载此文件? - How to download THIS file with javascript? 如何从存储下载文件 - How to download files from storage 如何使用javascript下载文件? - How to download file with javascript? 如何允许下载文件,该文件以二进制数据的形式从AJAX返回 - How to allow download of file, that is returned as binary data from AJAX 如何从HTMLUnit中的Javascript链接下载文件 - How to Download File from Javascript Link in HTMLUnit
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM