I'm working on a custom SPFX commandset. It opens a dialog with an iframe to an 3rth party platform. I'm able to receive a json through a postmessage. From this json, I convert it's data to a file, with it's proper metadata. All of this works like a charm... Except...
Now I want to upload this file to a document library, and it drives me crazy.
I'm referencing:
import "#pnp/polyfill-ie11";
import { ConsoleListener, Logger, LogLevel } from "#pnp/logging";
import { sp } from "#pnp/sp";
import { Web } from "#pnp/sp/webs";
import "#pnp/sp/webs";
import "#pnp/sp/files";
import "#pnp/sp/folders";
import { Base64 } from 'js-base64';
In my dialog component, I try to upload the file with web.getFolderByServerRelativeUrl. But this method is failing, and I really don't understand why.... Looking at the pnp reference (https://pnp.github.io/pnpjs/sp/files/), It seems like the right way.
var file = Base64.atob(response.Data);
console.log("File length : " + file.length);
let web = Web("https://MyTenant.sharepoint.com/sites/Customer"); // this is successful
await web.getFolderByServerRelativeUrl("/sites/Customer/Shared%20Documents/")
.files.add(response.fileName, file, true); // this fails
The context is set on the CommandSet onInit()
#override
public onInit(): Promise<void> {
Log.info(LOG_SOURCE, 'Initialized myCommandSet');
pnpSetup({
spfxContext: this.context
});
return Promise.resolve();
}
Hope you guys and girls can point me in the right direction...
EDIT:
Error:
HTTP400: INVALID REQUEST - The request could not be processed by the server
due to an invalid syntax
POST - https://MyDevTenant.sharepoint.com/sites/customer/
_api/web/getFolderByServerRelativeUrl
('%2Fsites%2Customer%2FShared%2520Documents%2F')
/files/add(overwrite=true,url='')
Is it the url from the documentlibrary that messes things up?
Thanks to Willman for giving me a right direction.
This did the trick:
import { sp, Web, IWeb } from "#pnp/sp/presets/all";
import "#pnp/sp/webs";
import "#pnp/sp/lists";
import "#pnp/sp/files";
import "#pnp/sp/folders";
const web = await sp.web();
const list = sp.web.getList("Documents");
const listId = await list.select("Id")();
await sp.web.lists.getById(listId.Id).rootFolder.files.add(docname, file, true);
Related
I am trying add a qr code scanning functionality to my react app. I am using #zxing(https://www.npmjs.com/package/#zxing/browser & https://www.npmjs.com/package/#zxing/library) packages.
Following the readme, here's my js code. I have hosted the application on aws so its SSL covered. But I can't seem to figure out the issue. I have read the git repo of both and the functions do exists(https://github.com/zxing-js/browser/tree/master/src/readers)
import React, { useState, useEffect } from "react";
import {
NotFoundException,
ChecksumException,
FormatException
} from "#zxing/library";
import { BrowserQRCodeReader, BrowserCodeReader } from '#zxing/browser';
export default function() {
var qrCodeReader = null;
var codeReader = null;
var sourceSelect = null;
console.log("ZXing code reader initialized");
useEffect(() => {
codeReader = new BrowserCodeReader();
qrCodeReader = new BrowserQRCodeReader();
console.log(codeReader.listVideoInputDevices()); // ISSUE: RETURNS -> listVideoInputDevices() is not a fuction
console.log(qrCodeReader.listVideoInputDevices()); // ISSUE: RETURNS -> listVideoInputDevices() is not a fuction
console.log("Code Reader", codeReader); // ISSUE: SEE IMAGE BELOW
console.log("QR Code Reader", qrCodeReader); // ISSUE: SEE IMAGE BELOW
}, []);
Instead of using the import try using:
`
const zxing = require('zxing-js/library');
`
so whenever I want to import a model via GLTFLoader locally I get this error:
JSON.parse: unexpected character at line 1 column 1 of the JSON data
but when I try it via a link it works.
The link I tried with is:
https://s3-us-west-2.amazonaws.com/s.cdpn.io/39255/ladybug.gltf
I tested the models I used in the official three.js-Editor and even exported them from there to get a "clean" gltf model. I also saved the content of the link in a gltf file and it didnt work neither.
This is my code:
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
async function run() {
try {
var loader = new GLTFLoader();
loader.crossOrigin = true;
loader.load(
"./scene.gltf",
//"https://s3-us-west-2.amazonaws.com/s.cdpn.io/39255/ladybug.gltf",
function (data) {
var object = data.scene;
object.position.set(0, 0, 0);
scene.add(object);
}
);
} catch (e) {
console.log(e);
}
}
run();
As Marquizzo said: You have to run a local server for the models. You cannot import them via a path normally, because of security restrictions.
Good Morning! I've been trying for hours how to make redirect page in middleware. I read the documentation and I'm using NextResponse.redirect('/about') and i get a message that: "Error: URLs is malformed. Please use only absolute URLs -"
If I enter the Absolute URL as: http://localhost:3000/about the browser keeps executing the request several times as shown in the image below.
I try this solution in Middleware Relative URLs, but the error persists.
Does anyone have any solution? Thanks.
Here is my code in _middleware.ts:
import { NextResponse } from 'next/server';
import type { NextFetchEvent, NextRequest } from 'next/server';
export function middleware(request: NextRequest, ev: NextFetchEvent) {
return NextResponse.redirect('/about')
}
The folder and the files localization:
The new version of next does not allow this anymore, indeed:
next/dist/server/web/utils.js (136:0) # Object.validateURL
I have not consulted official docs, while my solution was to pass on the origin:
export function middleware(req: NextRequest): NextResponse | null {
const { pathname, origin } = req.nextUrl
return NextResponse.rewrite(`${origin}/about`)
}
I'm delving into a React, Express and Typescript tutorial, to which I'm still pretty new to. Trying to better understand how setting up custom types works, and this is what I currently have.
In types.ts file:
import { Request, Response } from "express";
import { Redis } from "ioredis";
//import express from "express"; // adding this did not help
//import session from "express-session"; // adding this did not help
export type MyContext = {
req: Request; // & { session: Express.Session }; // this is my troublesome line
redis: Redis;
res: Response;
};
When trying to add
& { session: Express.Session }
I get the error:
any Namespace 'global.Express' has no exported member
'Session'.ts(2694)
Versions of devDepencies and also depencies have been compared so that they're the same. Trying the latest versions had no change.
devDependencies:
"#types/express": "^4.17.7",
"#types/express-session": "^1.17.0",
...
dependencies:
"express": "^4.17.1",
"express-session": "^1.17.1",
...
Things I've tried:
As comments show in the code, different import statements like express and/or session.
Changing strictNullChecks from true to false in package.json.
The latest versions of express, express-session, #types/express and #types/express-session.
Change type to interface.
Double checked similar questions before posting this (I had already looked here on SO and Google).
Comparing the tutorial's final code on GitHub vs my own code (they're the same as far as I can tell).
The error you are getting tells you that it's looking for a type in global.Express.Session. This is because you have no import called Express so it's trying to find it on the global scope. Of course, this does not exist!
This worked for me, assuming that the Session type was supposed to come from the express-session library:
import { Request, Response } from "express";
import { Redis } from "ioredis";
import session from "express-session";
export type MyContext = {
req: Request & { session: session.Session };
redis: Redis;
res: Response;
};
I believe the problem stemmed from different versions of a dependency used by express-session. I found the tutorial and this problem being discussed elsewhere (not on SO) but was able to make the changes below. req.session is available throughout my project now. In my use case, I wanted userId accessible via req.session.userId, so that's added (wasn't in original question).
import { Request, Response } from "express";
import { Session, SessionData } from "express-session";
import { Redis } from "ioredis";
export type MyContext = {
req: Request & {
session: Session & Partial<SessionData> & { userId: number };
};
redis: Redis;
res: Response;
};
In my React app (built with Create React App cli, and not ejected) I have it set up so if there is no REACT_APP_API_URL defined then it uses mocked data.
I do this by suppling a fakeFetch function to redux-api-middleware ala
import { apiMiddleware as aMl, createMiddleware } from 'redux-api-middleware'
import fakeFetch from 'fixtures/utils/fakeFetch'
const apiMiddleware = apiBase ? aMl : createMiddleware({ fetch: fakeFetch })
// etc... configure the `redux` store with the middleware
That's fine when developing, but I'd like for that code to be completely detached from the build when actually building for deployment.
Is there any way I can do something along the lines of
<% if process.env.REACT_APP_API_URL %>
import { apiMiddleware } from 'redux-api-middleware'
<% else %>
import { createMiddleware } from 'redux-api-middleware'
import fakeFetch from 'fixtures/utils/fakeFetch'
const apiMiddleware = createMiddleware({ fetch: fakeFetch })
<% endif %>
// etc... configure the `redux` store with the middleware
to prevent webpack from including up all my fixtures / fake data in the production build, while giving me a very simple way to switch between mock vs live data?
I do not want to have to eject the app, but am open to using a webpack plugin that's injected using Create React App Configuration Overrides.
I think webpack code-splitting with dynamic imports could be your best bet. This way, your mock data is bundled but never sent to the client (which I think is the main goal here).
import { apiMiddleware, createMiddleware } from 'redux-api-middleware'
const getMiddleware = async () => {
if (process.env.REACT_APP_API_URL) {
return apiMiddleware;
} else {
// loads bundle over network
const { default: fakeFetch } = await import('fixtures/utils/fakeFetch');
return createMiddleware({ fetch: fakeFetch });
}
}
I know this does not answer the question directly but on a side note, I think the cleanest way would be to utilise a mock sever such as mock-server.com. In development, you would just use the mock server url in process.env.REACT_APP_API_URL. This way, the test data lives in a completely different environment and provide a clear separation of concerns. You could probably also just create a simple local express app that just returns hardcoded JSON if you don't want to use third-party tools.