typescript 使用fetch向天体测量API提交URL

k3bvogb1  于 2023-02-13  发布在  TypeScript
关注(0)|答案(1)|浏览(97)

我有一个苗条的工具包和typescript项目。我有一个uploadPhoto/+page.server.ts文件包含:

import { ImgurClient } from 'imgur';
import type { PageServerLoad, Action, Actions } from './$types';
import { mssqlConnection } from '../../db/mssqldb';
import { Request } from 'mssql';
import { v4 as uuidv4 } from 'uuid';
import { fail, redirect } from '@sveltejs/kit';
let username: string;

export const load: PageServerLoad = async ({ locals }) => {
    if (!locals.user) {
        throw redirect(302, 'login');
    } else {
        username = locals.user.username;

        if (process.env.NOVA_KEY) {
            const sessionKey = await fetchAstrometrySessionKey(process.env.NOVA_KEY);
            console.log(sessionKey);
            const data=await submitURL(sessionKey, 'https://i.imgur.com/Q5i9bmX.jpg');
            console.log(data);
        }
    }
};
const client = new ImgurClient({
    accessToken: process.env.TOKEN,
    clientId: process.env.CLIENT_ID,
    clientSecret: process.env.CLIENT_SECRET,
    refreshToken: process.env.REFRESH_TOKEN
});

async function saveURL(url: string) {
    const connection = await mssqlConnection();
    const selectRequest = new Request(connection);
    const selectResult = await selectRequest
        .input('Username', username)
        .query('SELECT Id FROM Users WHERE Username = @Username');
    const id = selectResult.recordset[0].Id;
    console.log(id);
    const insertRequest = new Request(connection);
    const insertResult = await insertRequest
        .input('Id', uuidv4())
        .input('UserId', id)
        .input('ImageURL', url)
        .query('INSERT INTO UsersImages(Id, UserId, ImageURL) VALUES(@Id, @UserId, @ImageURL)');
    return insertResult === undefined;
}

async function uploadToUmgur(file: File) {
    const buffer = Buffer.from(await file.arrayBuffer());
    const base64 = buffer.toString('base64');
    const response = await client.upload({
        image: base64,
        type: 'base64'
    });
    console.log(response.data);
    return response.data;
}

async function fetchAstrometrySessionKey(apikey: string) {
    const response = await fetch('http://nova.astrometry.net/api/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
        },
        body: `request-json=${encodeURIComponent(JSON.stringify({ apikey }))}`
    });
    const data = await response.json();
    if (data.status !== 'success') {
        console.log('Could not obtain session key: ' + data.message);
    }
    return data.session;
}

async function submitURL(sessionId: string, url: string) {
    const options = {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: JSON.stringify({
            session: sessionId,
            url: url,
            scale_units: 'degwidth',
            scale_lower: 0.5,
            scale_upper: 1.0,
            center_ra: 290,
            center_dec: 11,
            radius: 2.0
        })
    };
    console.log(options.body)

    const response = await fetch('http://nova.astrometry.net/api/url_upload', options);
    const result = await response.json();

    if (result.status === 'success') {
        console.log(`Successful submission: ${result.subid} with hash ${result.hash}`);
        return result.subid;
    } else {
        console.error(result);
        return null;
    }
}

const upload: Action = async ({ request }) => {
    try {
        if (request.method === 'POST') {
            const form = await request.formData();
            const image = form.get('img') as File;
            console.log(form.get('img'));
            if (image) {
                console.log(`Received file with name: ${image.name}`);
                const link = (await uploadToUmgur(image)).link;
                console.log(link);
                if (await saveURL(link)) {
                    return link;
                } else {
                    fail(500, { error: true });
                }
            }
        }
    } catch (e) {
        console.log(e);
    }
};

export const actions: Actions = { upload };

只是为了测试的目的,我调用了fetchAstrometrySessionKey和submitURL。fetchAstrometrySessionKey工作正常。但是submitURL给我错误。当我尝试获取这个帖子请求时,我得到:

{ status: 'error', errormessage: 'no json' }

控制台输出如下:

asjoissd9fdg0fijdgf
{
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: '{"session":"7675zfa9ef8ddikpcplhx2akb42htcqo","url":"https://i.imgur.com/Q5i9bmX.jpg","scale_units":"degwidth","scale_lower":0.5,"scale_upper":1,"center_ra":290,"center_dec":11,"radius":2}'
}
{ status: 'error', errormessage: 'no json' }

字母和数字的字符串是会话(出于安全目的,这不是有效会话)。然后我记录选项变量。最后是响应
我曾尝试将应用程序/x-www-form-urlencoded更改为应用程序/json,但这次可能没有json或被终止

u3r8eeie

u3r8eeie1#

根据文档,您需要通过request-json字段将所有JSON作为application/x-www-form-urlencoded发送。
基本上,使用与您的 login 请求相同的格式

// note, no extra headers required when using URLSearchParams
const options = {
  method: 'POST',
  body: new URLSearchParams({
    "request-json": JSON.stringify({
      session: sessionId,
      url: url,
      scale_units: 'degwidth',
      scale_lower: 0.5,
      scale_upper: 1.0,
      center_ra: 290,
      center_dec: 11,
      radius: 2.0
    })
  }
};

const response = await fetch('http://nova.astrometry.net/api/url_upload', options);

相关问题