在Ember中使用Ember-cli-file-saver下载文件的技术求助
Hey Daniel, let's work through your problem clearly—your error and confusion around arraybuffer: true make total sense once you break down what's happening.
First, why that SyntaxError?
That error (Unexpected token P in JSON...) is happening because your Ajax request is trying to parse the API's response as JSON by default, but the API is returning a binary file (like a PDF, Excel, etc.). The "P" is probably the start of a PDF header (%PDF-1.7), which isn't valid JSON—so the parser chokes immediately.
Where to put arraybuffer: true (or responseType: 'arraybuffer')?
It depends on how you're making the request, but here are the two common scenarios:
1. Directly in your custom Ajax request (most straightforward)
If you're writing your own Ajax call (jQuery, native fetch, Axios), explicitly tell the request to handle the response as binary data instead of JSON. Here are working examples for popular tools:
jQuery Example:
$.ajax({ url: "/your-api-file-endpoint", method: "GET", // Tell jQuery to treat the response as arraybuffer xhrFields: { responseType: "arraybuffer" }, success: function(binaryData) { // Convert arraybuffer to Blob and trigger download const fileBlob = new Blob([binaryData], { type: "application/pdf" }); // Match your file's MIME type const downloadUrl = window.URL.createObjectURL(fileBlob); // Create a hidden link to trigger download const downloadLink = document.createElement("a"); downloadLink.href = downloadUrl; downloadLink.download = "generated-document.pdf"; // Name your file document.body.appendChild(downloadLink); downloadLink.click(); // Clean up window.URL.revokeObjectURL(downloadUrl); document.body.removeChild(downloadLink); }, error: function(xhr, status, err) { console.error("File download failed:", err); } });
Axios Example:
axios.get("/your-api-file-endpoint", { responseType: "arraybuffer" // Critical for binary files }) .then(response => { // Use the content-type header from the API to set Blob type const contentType = response.headers["content-type"]; const fileBlob = new Blob([response.data], { type: contentType }); // Same download logic as above const downloadUrl = window.URL.createObjectURL(fileBlob); const downloadLink = document.createElement("a"); downloadLink.href = downloadUrl; downloadLink.download = "generated-file.pdf"; document.body.appendChild(downloadLink); downloadLink.click(); window.URL.revokeObjectURL(downloadUrl); document.body.removeChild(downloadLink); }) .catch(err => { console.error("Download error:", err); });
2. In an application adapter (if you're using a framework's HTTP layer)
If you're using a global adapter (like an Axios interceptor or Vue Resource setup), you can target only this specific file download request to apply the responseType setting. For example, adding an interceptor in Axios:
axios.interceptors.request.use(config => { // Check if the request is for your file download endpoint if (config.url.includes("/your-api-file-endpoint")) { config.responseType = "arraybuffer"; } return config; });
This way, you don't break other requests that expect JSON responses.
Key Takeaway
Always set the response type to arraybuffer (or blob) for requests that download binary files. The easiest approach is to add it directly in the custom Ajax request for the file download—this keeps your configuration focused and avoids unintended side effects on other API calls.
内容的提问来源于stack exchange,提问作者DanielRestrepo

