我正在Angular中编写一个webapp,其中身份验证由JWT令牌处理,这意味着每个请求都有一个带有所有必要信息的"身份验证"标头.
这适用于REST调用,但我不明白我应该如何处理后端托管的文件的下载链接(这些文件驻留在托管webservices的同一服务器上).
我不能使用常规<a href='...'/>链接,因为它们不会携带任何标头,验证将失败.同样的各种咒语window.open(...).
我想到的一些解决方案:
以上所有都不太令人满意.
1是我现在使用的解决方案.我不喜欢它有两个原因:首先它不是理想的安全性,其次它可以工作,但它需要相当多的工作,特别是在服务器上:下载一些我需要调用一个生成一个新"随机"的服务"url,将它存储在某个地方(可能在数据库上)一段时间,并将其返回给客户端.客户端获取URL,并使用window.open或类似的.请求时,新URL应检查它是否仍然有效,然后返回数据.
2似乎至少同样多的工作.
3看起来很多工作,甚至使用可用的库,以及许多潜在的问题.(我需要提供自己的下载状态栏,将整个文件加载到内存中,然后要求用户在本地保存文件).
这个任务似乎是一个非常基本的任务,所以我想知道是否有更简单的东西我可以使用.
我不一定在寻找"Angular方式"的解决方案.常规Javascript会没事的.
AJAX请求和直接浏览器请求之间是否存在差异(就如何调用和加载网页而言)?
换句话说,我的意思是:是否以与客户端请求(由浏览器发起)不同的方式处理直接服务器端请求?
我正在使用vuejs 2 + axios.我需要发送一个get请求,将一些params传递给服务器,并获得一个PDF作为响应.服务器使用Laravel.
所以
axios.get(`order-results/${id}/export-pdf`, { params: { ... }})
Run Code Online (Sandbox Code Playgroud)
成功请求,但它不会启动强制下载,即使服务器返回正确的标头.
我认为这是一种典型情况,例如,您需要形成PDF报告并将一些过滤器传递给服务器.那怎么可能实现呢?
更新
所以实际上我找到了解决方案.然而同样的方法不适用于axios,不知道为什么,这就是我使用原始XHR对象的原因.所以解决方案是创建一个blob对象和用户createUrlObject函数.示例示例:
let xhr = new XMLHttpRequest()
xhr.open('POST', Vue.config.baseUrl + `order-results/${id}/export-pdf`, true)
xhr.setRequestHeader("Authorization", 'Bearer ' + this.token())
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
xhr.responseType = 'arraybuffer'
xhr.onload = function(e) {
if (this.status === 200) {
let blob = new Blob([this.response], { type:"application/pdf" })
let link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = 'Results.pdf'
link.click()
}
}
Run Code Online (Sandbox Code Playgroud)
重要提示:您应该将数组缓冲区作为响应类型
但是,在axios中编写的相同代码返回的PDF为空:
axios.post(`order-results/${id}/export-pdf`, {
data,
responseType: 'arraybuffer'
}).then((response) => {
console.log(response)
let blob …Run Code Online (Sandbox Code Playgroud) 我收到文件网址作为api的回复.当用户单击下载按钮时,应该下载该文件而不在新选项卡中打开文件预览.如何实现这个反应js?
有一个页面(url),我通过XMLHttpRequest请求它,但是我没有得到请求的URL的响应,它正在将请求发送到另一个页面,
请求---> page.php
从> directedpage.php获取响应
问题是如何获得响应网址?(示例中为directedpage.php)
我的 api 的响应类似于此演示 [URL][https://mytutari.com/webservices/contract/exportcallnote/10377431] 如果我单击 url,它会自动下载。但是当我尝试在 axios 响应中使用 POST 请求发布一些数据时,我得到了如何处理的信息。\n API 响应
\n> PKk)S docProps/PKk)S\xc3\xa9\xc3\x83\xe2\x84\xa2\xc2\xa3docProps/app.xml\xc3\x8f1\xc6\x920\xc3\xa0\xc2\xbd\xc2\xbfB\xc2\xb2kl\xe2\x80\xa1R$\xc3\xaaR:w\xc2\xb0\xc3\x9dCrj\xc3\x80\xc3\x9cIr\xc3\xbd\xc3\xb7M)\xc3\x94\xc2\xbd\xc3\xa3\xc3\xa3\xc3\x81\xc3\x87{\xc2\xaa]\xc3\xbd\xe2\x80\x9d-\xc2\xa2#\xc2\xac\xc3\x85\xc2\xb1(Eh\xc3\x88:j\xc3\xb1\xc3\xa8n\xc3\xb9Ed\xe2\x80\x985Z=B-6\xcb\x86\xc2\xa2m\xc3\xaah\xe2\x80\xa0\xc3\x80b\xe2\x80\x93\xc5\x92\xc2\xb5\xe2\x84\xa2\xc3\xa7J\xc3\x8ahF\xc3\xb0:\xc2\xa9\xc3\x86\xc3\x94\xc3\xb4\xc2\xbc\xc3\xa6\xc3\x83\n> \xc2\xa9\xc3\xaf+\xe2\x84\xa2\xe2\x80\x94dy*\xc3\x8b\xc2\xb3\xe2\x80\x9e\xe2\x80\xa2-\xc3\x98|\xc3\xbe\xc3\xa2+V\xc3\xbf\xe2\x80\xb9Z2\xc5\xb8}\xc3\xb1\xc3\x99ms\xc3\xb2\xc3\x95\xc3\xab\xc2\xa9s\xc5\xa1R\xc3\x89=(\xc2\xb9\xc3\x9fh\xc3\x9ePKk)S\xe2\x80\xa6]\xc3\x98\xc3\x93\n> docProps/core.xmlm\xe2\x80\x98\xc3\x8bN\xc3\x830E\xc3\xb7|E\xc3\xa4}b;\xc2\xa8\xc2\xb2\xe2\x80\x99t*\xc3\x98 \xc3\x8eZ\xc3\x84\xc3\x99\xc2\xa6i\xc3\xb9z\xe2\x80\x99\xc2\xb4\n> u\xc3\xa7\xc3\xb1=>\xc5\xa1\xc3\xb1\xe2\x80\xb9\xc2\xadn\xe2\x80\x9c \xc3\xba\xc2\xa0\xc2\xac) \xc3\x8fI\xc3\x90H[+\xc3\x93\xe2\x80\x9d\xc3\xa4y\xc2\xb5L\xc3\xa7$ L\n> \xc2\xad5X\xe2\x80\x99\xc2\xb2\xc2\xa8.PKk)S docProps/PKk)S\xc3\xa9\xc3\x83\xe2\x84\xa2\xc2\xa3docProps/app.xml\xc3\x8f1\xc6\x920\xc3\xa0\xc2\xbd\xc2\xbfB\xc2\xb2kl\xe2\x80\xa1R$\xc3\xaaR:w\xc2\xb0\xc3\x9dCrj\xc3\x80\xc3\x9cIr\xc3\xbd\xc3\xb7M)\xc3\x94\xc2\xbd\xc3\xa3\xc3\xa3\xc3\x81\xc3\x87{\xc2\xaa]\xc3\xbd\xe2\x80\x9d-\xc2\xa2#\xc2\xac\xc3\x85\xc2\xb1(Eh\xc3\x88:j\xc3\xb1\xc3\xa8n\xc3\xb9Ed\xe2\x80\x985Z=B-6\xcb\x86\xc2\xa2m\xc3\xaah\xe2\x80\xa0\xc3\x80b\xe2\x80\x93\xc5\x92\xc2\xb5\xe2\x84\xa2\xc3\xa7J\xc3\x8ahF\xc3\xb0:\xc2\xa9\xc3\x86\xc3\x94\xc3\xb4\xc2\xbc\xc3\xa6\xc3\x83\n> \xc2\xa9\xc3\xaf+\xe2\x84\xa2\xe2\x80\x94dy*\xc3\x8b\xc2\xb3\xe2\x80\x9e\xe2\x80\xa2-\xc3\x98|\xc3\xbe\xc3\xa2+V\xc3\xbf\xe2\x80\xb9Z2\xc5\xb8}\xc3\xb1\xc3\x99ms\xc3\xb2\xc3\x95\xc3\xab\xc2\xa9s\xc5\xa1R\xc3\x89=(\xc2\xb9\xc3\x9fh\xc3\x9ePKk)S\xe2\x80\xa6]\xc3\x98\xc3\x93\n> docProps/core.xmlm\xe2\x80\x98\xc3\x8bN\xc3\x830E\xc3\xb7|E\xc3\xa4}b;\xc2\xa8\xc2\xb2\xe2\x80\x99t*\xc3\x98 \xc3\x8eZ\xc3\x84\xc3\x99\xc2\xa6i\xc3\xb9z\xe2\x80\x99\xc2\xb4\n> u\xc3\xa7\xc3\xb1=>\xc5\xa1\xc3\xb1\xe2\x80\xb9\xc2\xadn\xe2\x80\x9c \xc3\xba\xc2\xa0\xc2\xac) \xc3\x8fI\xc3\x90H[+\xc3\x93\xe2\x80\x9d\xc3\xa4y\xc2\xb5L\xc3\xa7$ L \xc2\xad5X\xe2\x80\x99\xc2\xb2\xc2\xa8.\nRun Code Online (Sandbox Code Playgroud)\nAPI调用
\n ```const formData = new FormData();\nformData.append("DealerID", DealerID);\nformData.append("FomDate", fromdate);\nformData.append("ToDate", toDate);\nformData.append("FixedDateParameter", FixedDateParameter);\nformData.append("export_type", export_type);\n//api\nconst dashboardexport_response = await dashboardexport({ formData });```\nRun Code Online (Sandbox Code Playgroud)\n仪表板导出
\n let url = API + "/dashboard/dashboardexport";\n\n formData.append("pcp_user_id", pcp_user_id);\n formData.append("role_id", role_id);\n formData.append("user_id", user_id);\n try {\n const response = await axios.post(url, formData, { header });\n return response.data;\n …Run Code Online (Sandbox Code Playgroud) 我以前使用 Axios 下载由 GET 端点提供的文件。端点已更改,现在是 POST,但不需要参数。我正在更新原始下载方法,但返回的文件已损坏。
downloadTemplate() {
axios.post(DOWNLOAD_TEMPLATE_URL,
{
responseType: 'blob',
headers: {
'Content-Disposition': "attachment; filename=template.xlsx",
'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}
})
.then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', 'template.xlsx');
document.body.appendChild(link);
link.click();
})
.catch((error) => console.log(error));
}
Run Code Online (Sandbox Code Playgroud)
我不知道,如果问题出在responseType,headers或如何响应的处理或全部的上方。到目前为止,我已经尝试了各种选择,但都没有运气。任何建议将不胜感激!
我已经能够使用 Postman 下载文件,所以我知道端点提供的文件很好。我只是无法在我的 React 代码中整理出执行此操作的参数。
我正试图通过像这样的axios来获取来自api调用的请求的'Content-Disposition'标题:
axios.get('Group/GetGroupObjectives', {
params: { periodId, isPreliminary },
responseType: 'arraybuffer',
})
.then((response) => {
if (response) {
response.request.getResponseHeader('Content-Disposition');
} else {
dispatch(docDownloadFailed());
}
})
Run Code Online (Sandbox Code Playgroud)
当我得到标题抛出此错误"拒绝得到不安全的标题"内容 - 处置""
这个问题是由api中的Cors引起的,但我得到了在响应头中正确获取头所需的所有头:
Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:*
Access-Control-Request-Headers:*
Cache-Control:no-cache
Content-Disposition:attachment; filename="sample.xlsx"
Content-Length:7965
Content-Type:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Date:Fri, 26 Jan 2018 14:35:38 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/10.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?RDpcVGVhbV9Tb2Zhc2FcRXh0cmFuZXRcRXh
Run Code Online (Sandbox Code Playgroud)
如何通过axios调用正确获取响应头?
由于某种原因axios-cache-adapter,没有缓存GET文件下载请求,我认为这是由于responseType: 'blob'axios 生成 src 所需的设置(因为我对不需要设置此字段的其他请求没有缓存问题)网址(根据这个答案):
src: URL.createObjectURL(new Blob([response.data])),
我的适配器设置如下:
// set axios defaults
axios.defaults.headers.common = {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
};
const configureAxios = async () => {
await localforage.defineDriver(memoryDriver);
const forageStore = localforage.createInstance({
driver: [
localforage.INDEXEDDB,
localforage.LOCALSTORAGE,
memoryDriver._driver
],
name: 'my-cache'
});
return setup({
// `axios-cache-adapter` options
cache: {
maxAge: 15 * 60 * 1000,
exclude: {
query: false
},
store: forageStore,
}
});
};
// call this function in …Run Code Online (Sandbox Code Playgroud) 我已经filesystem使用multer
我的服务器是node,客户端是react.
我在客户端下载和显示保存的文件时遇到问题 react
每当我这样做时,res.download(file)都会因为客户端拒绝连接而引发错误。
我的代码如下:
用户上传映射.js
const mongoose = require("mongoose");
const UserToUploadMapping = new mongoose.Schema({
userId: {
type:String,
required:true
},
file: {
type: Object,
required: true,
},
date: {
type: Date,
default: Date.now,
},
});
module.exports = mongoose.model("UserToUploadMapping", UserToUploadMapping);
Run Code Online (Sandbox Code Playgroud)
上传视频.js
const router = require("express").Router();
const multer = require('multer');
const UserToUploadMapping = require('../models/UserToUploadMapping')
let nameFile = ''
const storage = multer.diskStorage({
destination:'./Videos',
filename:(req,file,cb) => {
console.log(file)
nameFile = file.originalname + " …Run Code Online (Sandbox Code Playgroud)